概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Performance Improvements in Ruby 2.5
- 原文公開: 2017/11
- 著者: Jesus Castello
- サイト: http://www.rubyguides.com/
Ruby 2.5のパフォーマンス改善点(翻訳)
Rubyは常に改善を繰り返しており、Ruby 2.5でも同様です。
Ruby 2.5でいくつかの最適化が行われました。
- サイズの大きな文字列を作成したときの式展開が約72%高速化
String#prepend
の引数が1つだけの場合に約42%高速化Enumerable#sort_by
、Enumerable#min_by
、Enumerable#max_by
が約50%高速化
ベンチマークを見てみましょう。
文字列の式展開パフォーマンス
この最適化のコミットメッセージに含まれていたコード例を使いました。
require 'benchmark/ips'
Benchmark.ips do |x|
x.report "Large string interpolation" do |t|
a = "Hellooooooooooooooooooooooooooooooooooooooooooooooooooo"
b = "Wooooooooooooooooooooooooooooooooooooooooooooooooooorld"
t.times { "#{a}, #{b}!" }
end
x.report "Small string interpolation" do |t|
a = "Hello"
b = "World"
t.times { "#{a}, #{b}!" }
end
x.compare!
end
以下の結果を得ました。
- Ruby 2.4.1:
Small string interpolation: 3236291.1 i/s
Large string interpolation: 1711633.4 i/s - 上より1.89倍遅い
- Ruby 2.5:
Small string interpolation: 3125175.1 i/s
Large string interpolation: 2555782.6 i/s - 上より1.22倍遅い
見てのとおり、サイズの大きな文字列でパフォーマンスがかなり向上しました。
String#prepend
のパフォーマンス
prepend
メソッドは、arrayの先頭にテキストを挿入します。
Ruby 2.5では、もっともよく使われるケースとして文字列を1つだけ追加する場合の最適化を行いました。
ベンチマーク結果は次のとおりです。
- Ruby 2.4.1:
String#prepend 3.428M (± 3.2%) i/s - 17.159M in 5.011008s
- Ruby 2.5:
String#prepend 4.638M (± 3.6%) i/s - 23.276M in 5.025562s
これはなかなかの改善です。
Enumerableのパフォーマンス改善
いくつかのEnumerableメソッドでパフォーマンスが向上しました。
この最適化では<=>
メソッドのディスパッチメソッドをスキップすることでパフォーマンスが向上します。
コミットメッセージには以下の記述があります。
Fixnum/Float/String
オブジェクトへのディスパッチで、<=>
メソッドではなくOPTIMIZED_CMP()
を使う
同リンクより抄訳
ベンチマーク結果は次のとおりです。
- Ruby 2.4.2:
Enumerable#sort_by 2.395k (± 6.7%) i/s - 11.952k in 5.014422s
Enumerable#min_by 8.244k (± 6.1%) i/s - 41.405k in 5.042327s
Enumerable#max_by 8.053k (± 6.7%) i/s - 40.180k in 5.015375s
- Ruby 2.5:
Enumerable#sort_by 5.914k (± 6.7%) i/s - 29.786k in 5.062584s
Enumerable#min_by 15.668k (± 3.0%) i/s - 78.888k in 5.039748s
Enumerable#max_by 15.544k (± 2.3%) i/s - 78.408k in 5.046709s
50%ほど向上していますね🙂
Range#min
とRange#max
他にも2つのパフォーマンス改善があります。
ベンチマーク結果は次のとおりです。
- Ruby 2.4.2
Range#min 7.976M (± 3.0%) i/s - 39.950M in 5.013242s
Range#max 7.996M (± 3.4%) i/s - 40.059M in 5.015984s
- Ruby 2.5
Range#min 13.154M (± 3.0%) i/s - 65.731M in 5.002094s
Range#max 13.021M (± 2.6%) i/s - 65.202M in 5.010924s
コミットはこちら。
String#scan
の改善
コミットメッセージによると、文字列パターンで50%、正規表現パターンで10%パフォーマンスが向上したとのことです。
ベンチマークをチェックしてみましょう。
- Ruby 2.4.2
String#scan - String pattern
1.367M (±19.8%) i/s - 6.458M in 4.982047s
String#scan - Regex pattern
1.228M (±17.0%) i/s - 5.881M in 4.983943s
Ruby 2.5
String#scan - String pattern
3.944M (±24.4%) i/s - 17.739M in 4.977417s
String#scan - Regex pattern
1.696M (±17.4%) i/s - 8.103M in 4.982614s
高速化したscan
に乾杯!
まとめ
12/25にリリース予定のRuby 2.5で導入される新しい最適化について解説しました。
最適化は、文字列の式展開、Enumerableメソッド、String#prepend
メソッド、String#scan
メソッド、そしてRange#max
/ Range#mix
で行われました。
本記事がお役に立てば幸いです。
ぜひ、好みのSNSで本記事をシェアしてください(元記事からどうぞ)🙂