Ruby1.9で遅くなる項目

Ruby1.8と1.9でのベンチマーク結果が公開されている。

緑の項目はRuby1.9で速くなった項目、赤い項目は逆に遅くなった項目である。また灰色の項目は、Ruby1.8がstack overflowでエラーになったか、Ruby1.9が遅すぎて表示されていないかのどちらかである。


これを見る限り、Ruby1.9では以下の項目が遅くなるようだ。


以下詳細。


ベンチマーク結果を見ると、Ruby1.8と比べてRuby1.9は全般的に高速化されていることが分かる。しかしすべての項目で高速化されているわけではなく、以下のベンチマークでは逆に遅くなっている。

  • app_raise (+21%)
  • io_file_create (+13%)
  • io_file_read (+38%)
  • so_count_words (Ruby 1.9 too slow (> 8x))
  • so_pidigits (+15%)
  • so_reverse_complement (+44%)
  • vm2_mutex (+16%)
  • vm2_regexp (+37%)
  • vm3_thread_create_join (Ruby 1.9 too slow (> 8x))
  • lib_coderay (+6%)
  • interpreter_start (+118%)
  • interpreter_require (+67%)


これをふまえて、Ruby1.9の特徴を考えてみた。

  • io_file_create (+13%) と io_file_read (+38%) から、I/Oがらみが遅くなっているのが分かる。しかしVMを変えたからといってI/O周りの性能に影響が出るとは考えにくい。謎だ。しかもファイルの読み込みが4割も遅くなるのであれば、例えば設定ファイルやテンプレートの読み込みが遅くなるわけで、アプリケーションの速度に大きく影響するはず。正直言ってこれはいただけない。
  • so_reverse_complement (+44%) は何のベンチマークかよく分からないが、内部でデータファイルを読み込んでいる箇所があったから、1.9で遅くなっているのはこのせいだと思う。
  • so_count_words はファイルを読み込んで、文字数と行数と単語数を数えている。これが8倍以上も遅いという結果になっているが、原因は不明。ベンチマークプログラムを見るとファイルを読み込んでいる箇所があるが、それだけで8倍も遅くなるとは思えない。
  • app_raise (+21%) は、例外のハンドリングが遅くなっていることを表す。ただこれは、try - catch ブロックを用意するのが遅くなっているのか、それとも例外をthrowするのが遅くなっているのか、あるいは両方なのか、分からない。
  • vm3_thread_create_join が8倍以上遅くなっている。これは恐らく、スレッド周りのチューニングがまだ十分には行われていないことが原因なんだろう(注:推測)。開発が進んでいけば、いずれは解消されると思われる。
  • vm2_mutex (+16%) も、チューニングが進めば解消されると思われる(楽観しすぎ?)。
  • vm2_eval (> 3x) は、evalが3倍以上遅くなることを意味する。1.9ではコードのcompileに時間がかかるので遅くなるのは確かなのだろうが、3倍も遅いというのはちょっと解せない。個人的には、スクリプト言語C++Javaと比べたとき、evalがあることはスクリプト言語の大変大きなアドバンテージだと思っているので、Ruby1.9のevalが改善されずに遅いまま放置されているのは大変残念である。eRubyとかはeval使いまくりのはずなんだから、Webアプリは遅くなるんじゃなかろうか。
  • vm2_regexp (+37%) により、正規表現が遅くなっていることが分かる。Ruby1.9では正規表現エンジンが新しくなって機能が強化されているかわりに、スピードが犠牲になっているのだろう。個人的には、正規表現の機能は現状でも十分なので、スピードを落とすことは止めてほしかった。
  • app_factorialとso_ackermannが、Ruby1.8ではstack overflowを起こしている。これらは両方とも再帰呼び出しが深くなるのが特徴である。Ruby1.9では問題なく実行できていることから、Ruby1.9ではメソッド呼び出しにおけるstackの消費量が削減されていると思われる*1
  • iterpreter_start (+118%) はインタープリタの起動に2倍の時間がかかることを意味する。どうもbyte code interpreterは全般的に起動が遅くなる傾向があるようだ(Javaしかり、Pythonしかり)。簡単なCGIアプリケーションなら、Ruby1.9にしたら逆に遅くなるだろう。
  • interpreter_require (+67%) はライブラリのロードが遅くなることを意味する。Ruby1.9では、まずRuby1.8と同じように構文木を生成し、そのあとでバイトコードに変換しているらしいから、このような結果になるのだろう。これもCGIアプリケーションが遅くなる結果に繋がる。EmacsPythonのように、byte code compileしたものをファイルに保存する機能が必要だ(仕様もEmacsPythonと同じでいいだろう)。


・・・


まとめてみよう。Ruby1.9では以下が遅くなるみたいだ。


これを見ると、スレッド関連以外はWebアプリケーションに直接影響を与えるものばかりだ。最後の2つはmod_rubyFastCGIなら関係ないが、CGIアプリケーョンにとっては重大な問題だ(レンタルサーバーで掲示板やブログのCGIを動かしている人は多いだろう)。またI/O周りが遅いとなると、設定ファイルやテンプレートの読み込みや、あとセッションファイルの作成と読み込みも遅くなるわけだから、シングルスレッドのアプリケーションでは影響が大きい。


こうしてみると、Ruby1.9でほんとにアプリケーションが速くなるのか、ちょっと疑問だ(フィボナッチ数列が速くなってもWebアプリが遅くなったのでは話にならない)。実際には速くはなるんだろうけど、劇的な向上というほどではなさそう。


・・・ということを書いたら叩かれるだろうから補足しておくと、Ruby1.9をdisろうとしているわけじゃなくて、「Ruby1.9にあまり過度な期待をすべきではない」ということが言いたかった。Ruby1.9にしたら確かにFibonacci seriesの計算は5倍速くなるかもしれないが、アプリケーションが何でも5倍速くなるわけではない(そもそも体感速度が速くなるかどうかも分からない)。そのことが分かってなくて過度な期待をしている人が多いみたいなので、あえて批判的なことを書いてみた。


だれかRuby1.9Ruby on Railsベンチマークとってないだろうか。・・・と思って探したら、見つかった。2007年3月の資料なので少し古いが、参考になるだろう。

これを見る限り、多少速くはなるようだが、目に見えてというにはほど遠いようだ。

*1:Ruby1.9が深い再帰呼び出しでもstack overflowを起こさないのは末尾再帰呼び出しの除去を行っているためも考えられるが、Ruby1.9ではdisableになっていると聞いているので、そうではないと思う。