Re: Ruby 1.9 で eval が遅いという話

なんというか、頭のいい人は結論だけ語って途中をすっ飛ばすから困る。

コンパイルフェーズを追加して仮想マシンで実行するようにしたら、3倍遅くなっても全く不思議ではないと思う。

Ruby 1.9 で eval が遅いという話 - odz buffer

仮想マシンの仕組みを知らない自分からすれば、『コンパイルフェーズを追加して仮想マシンで実行する』ことと『3倍遅くなっても全く不思議ではない』という結論の間には10光年ぐらいの開きを感じるけど、すでに仕組みを知っている人はその距離を何の苦もなくワープできるんだろう。


まあ『仮想マシンで実行する』ことが遅くなる原因とは思えないから(Ruby1.9仮想マシンにするから速くなるのであって、それで遅くなるなら本末転倒)、遅くなる原因は結局『コンパイルフェーズを追加』したことだけなんだろうけど、それだけで3倍も遅くなるというのがやっぱりわからない。コンパイルって、結局は構文木をbyte codeに変換することだと思うけど、構文木を辿って変換するコストがそんなにかかるとは思えない。


あとはbyte codeの最適化をしている可能性があるのか。どのような最適化をしているのかによっては、確かに3倍くらい遅くなるかもしれない。そもそも最適化をしているのかどうかも知らないけど。


VMの仕組みを知らない素人からみると、evalするたびになんか環境の初期化というかリセットみたいなのが必要で、そのコストが大きいからevalに時間がかかるのかと想像してたけど、上の記事から察するにはそうではないようで、純粋にコンパイルに時間がかかるようだ。


しかしそうだとすると、前に書いたようにinterpreter_requireベンチマークは7割くらいの性能ダウンで済んでいる理由が説明できない。素人考えでは、interpreter_requireが70%ダウンならevalも70%程度ですむはずで、でも実際には3倍遅いわけだから、evalが遅いのはコンパイル以外にも原因があるんじゃないか、と考えたわけだが。

ささださんがいうように、素直にベンチマークのコードを見てみればいいと思うのだけど。

Ruby 1.9 で eval が遅いという話 - odz buffer

こんなコードから原因が分かるわけないじゃん!なんでこれを見たらevalが3倍遅くなる理由が分かると思うんだろう。


これだから頭のいい人は(略


evalベンチマークのコードから見て分かることは、

  • whileループで6,000,000回繰り返している
  • Ruby1.9ではwhileループは速くなっているのに、evalベンチマークは遅くなっている
  • → 実はevalが遅くなっているのは、3倍どころじゃないんじゃね?*1

ということかなあ。VMの仕組みを知らない素人ではこれが限界。どう考えても、evalが遅くなる原因までは読み取れません。


・・・


Rubyって、文字列だけじゃなくてblockもevalできたよね。文字列をevalするのと違い、blockをevalするならコンパイルフェーズに時間がかかるということはないはず。こんど実験してみる。

*1:もしベンチマークでwhileループの時間を控除するようになっていたら、この考えは大ハズレ。