通过添加一些 gems 来提升 Rails 应用的性能 已翻译 100%

oschina 投递于 2014/07/03 06:30 (共 5 段, 翻译完成于 07-03)
阅读 2337
收藏 36
3
加载中

Working with Rails for some time you start nitpicking on how to improve it. This is a first in the series of articles regarding on how to improve (even marginally) Rails's performance.

I'll focus on a bunch of gems that speed up, in some cases considerably, small parts of Rails, like the html escaping, the String#blank? and JSON utils.

Benchmarking methodology

Methodology is a strong word for just running a couple of times in the console wrk but I'm not searching for the holy grail here, just to get a raw idea.

I switched from the old apache ab to wrk redirect:

wrk is a modern HTTP benchmarking tool capable of generating significant
 load when run on a single multi-core CPU.

wrk -t10 -c10 -d10s http://localhost:3000

This runs a benchmark for 10 seconds, using 10 threads, and keeping 50 HTTP connections open i.e. this should suffice. Just remember to benchmark on your actual app to see the real improvements.

已有 1 人翻译此段
我来翻译

The escape_utils gem

Just faster all html escaping via the lovely escape_utils redirect gem. In order to use it in Rails one needs to add an initializer that patches things up:

begin
  require 'escape_utils/html/rack' # to patch Rack::Utils
  require 'escape_utils/html/erb' # to patch ERB::Util
  require 'escape_utils/html/cgi' # to patch CGI
  require 'escape_utils/html/haml' # to patch Haml::Helpers
rescue LoadError
  Rails.logger.info 'Escape_utils is not in the gemfile'
end

The logic to test it:

def escape_utils
  @escape_me = <<-HTML
    <body class="application articles_show">
      <!-- Responsive navigation
      ==================================================== -->
      <div class="container">
        <nav id="nav">
      <ul>
        <li><a href="/"><i class="ss-standard ss-home"></i>home</a></li>
        <li><a href="/home/about"><i class="ss-standard ss-info"></i>about</a></li>
        <li><a href="/contact"><i class="ss-standard ss-ellipsischat"></i>contact</a></li>
        <li><a href="/home/projects"><i class="ss-standard ss-fork"></i>projects</a></li>
        <li><a href="/tags"><i class="ss-standard ss-tag"></i>tags</a></li>
        <li><a href="/articles?query=code"><i class="ss-standard ss-search"></i>search</a></li>
      </ul>
    </nav>
    <a href="#" class="ss-standard ss-list" id="nav-toggle" aria-hidden="true"></a>
  HTML

  render inline: "Hello  world <%= @escape_me %>"
end

With standard Rails:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    35.40ms    3.55ms  64.70ms   91.98%
    Req/Sec   142.19     11.68   164.00     83.12%
  2837 requests in 10.00s, 4.92MB read
Requests/sec:    283.61
Transfer/sec:    503.34KB

With the escape_utils gem:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    34.06ms    3.89ms  63.92ms   89.10%
    Req/Sec   148.65     13.36   180.00     75.94%
  2960 requests in 10.00s, 5.46MB read
Requests/sec:    295.98
Transfer/sec:    558.72KB
已有 1 人翻译此段
我来翻译

The fast_blank gem

Living under the impression that the blank? method is too slow? say no more and just try the fast_blank redirect gem!

Just add gem 'fast_blank' to your Gemfile and this should speed up quite nicely the String#blank? method as described in this article redirect. For testing I just added this code:

fast_blank is a simple extension which provides a fast implementation of active support's string#blank? function

 def fast_blank_test
    n = 1000

    strings = [
      "",
      "\r\n\r\n  ",
      "this is a test",
      "   this is a longer test",
      "   this is a longer test
      this is a longer test
      this is a longer test
      this is a longer test
      this is a longer test"
    ]

    Benchmark.bmbm  do |x|
      strings.each do |s|
        x.report("Fast Blank #{s.length}    :") do
          n.times { s.blank? }
        end
      end
    end

    render nothing: true
  end

With standard Rails:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.40s   207.72ms   1.58s    92.68%
    Req/Sec     3.10      2.11     6.00     53.66%
  69 requests in 10.01s, 33.08KB read
Requests/sec:      6.90
Transfer/sec:      3.31KB

With the fast_blank gem:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.33s   179.56ms   1.41s    93.33%
    Req/Sec     3.07      0.80     4.00     40.00%
  72 requests in 10.00s, 34.52KB read
Requests/sec:      7.20
Transfer/sec:      3.45KB
已有 1 人翻译此段
我来翻译

The oj gem

# oj gem
gem 'oj'
gem 'oj_mimic_json' # we need this for Rails 4.1.x

The test logic is simple, just serialize all articles into JSON:

class SidechannelsController < ApplicationController
  def oj
    render json: Article.all
  end
end

With standard Rails serializers:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   108.37ms    5.12ms 134.90ms   83.33%
    Req/Sec    45.76      3.60    55.00     57.69%
  922 requests in 10.00s, 57.41MB read
Requests/sec:     92.17
Transfer/sec:      5.74MB

With oj gem:

Running 10s test @ http://localhost:3000/sidechannels/bench
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    78.06ms    4.43ms  92.83ms   81.31%
    Req/Sec    63.64      5.33    71.00     64.49%
  1277 requests in 10.00s, 79.83MB read
Requests/sec:    127.65
Transfer/sec:      7.98MB

Using jemalloc

OK, this is not really a gem, if you want to dig into it then do check out my gist redirect. On initial testing it won't yield much performance gains, at least for my use case.

note: it will be included by default in Ruby at some point.

update: do try the jemalloc redirect gem by kzk:

gem install jemalloc

je -v rails s

Dig into your Rails app

Fear not and use MiniProfiler redirect with the awesome FlameGraphs redirect  by Sam Saffron.

已有 1 人翻译此段
我来翻译

Conclusion

Depending on what your app is doing you might want to add to your Gemfile some of these gems, I usually add them all just for good measure (you might want to check your RAM usage and have a full test suite before doing this though).

The oj gem is just great for a Rails based JSON API where you can drop the views and just serialize using representers or your pattern of choice.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(15)

小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释

引用来自“小石像怪”的评论

DJm
:w
小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释

引用来自“小石像怪”的评论

DJm
:w
小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释

引用来自“小石像怪”的评论

DJm
W1
小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释

引用来自“小石像怪”的评论

DJm
wW1
小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释
DJm
小石像怪
小石像怪

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。

引用来自“鱼说还休”的评论

可读性,开发高效性和维护性高于性能,爱ruby不解释
DJm
小石像怪
小石像怪

引用来自“朱尚述”的评论

这玩儿在中国用的不多呀!!!
iPad mini 2 16GB版的售价调低至2198元,32GB版售价2588元,4G蜂窝网络版售价分别为3088元和3488元。
鱼说还休
鱼说还休

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?

引用来自“Zoker”的评论

我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。
可读性,开发高效性和维护性高于性能,爱ruby不解释
无所谓了
无所谓了
这玩儿在中国用的不多呀!!!
Zoker
Zoker

引用来自“zjtxqjj”的评论

Ruby的性能比PHP好吧,就是太笨重了

引用来自“Zoker”的评论

感觉上是挺笨重,但是比php方便。

引用来自“Neo”的评论

ruby比php快?这不科学,不是php,python,ruby里面最快就是php吗?
我是说方便…我从来都不去讲语言的快慢,因为我认为如果不深入,再好的语言也写不出高效的程序。
返回顶部
顶部