ruby1.8でメソッドキャッシュが無いとどれぐらい遅くなるのか(竹内関数)
Ruby1.8はメソッド呼出のとき、スーパークラスをたどりながらメソッドの実体を検索するのだが、メソッド呼出のたびに検索するのでは効率が悪いのでメソッドキャッシュというキャッシュを使う。Rubyソースコード完全解説をCSNagoyaで読んでいたときに「キャッシュが無ければどの程度遅くなるのか」という話題がでたので、まずは竹内関数を使って比較した。
ruby1.8.7-p249のeval.cのrb_call()の
if (ent->mid == mid && ent->klass == klass) {
ってところを
if (ent->mid == mid && ent->klass == klass && 1 == 0) {
としてメソッドキャッシュを検索しないものと、なにも変更していないものをそれぞれコンパイルし、竹内関数でベンチマークをした。(コードは404 blog not foundのものを借用した)
/home/user> time ./ruby1.8-nocache/bin/ruby1.8nocache csnagoya/tak.rb 18 12 6 tak(18, 12, 6) = 18 real 0m34.278s user 0m25.030s sys 0m0.060s /home/user> time ./ruby1.8-normal/bin/ruby csnagoya/tak.rb 18 12 6 tak(18, 12, 6) = 18 real 0m16.845s user 0m16.570s sys 0m0.070s
上がキャッシュなし、下がキャッシュありだ。このデータだとキャッシュがある方が45%ぐらい速くなっている。この45%がプログラムの特性によってどうかわるかは誰かが調べてほしい。
(ちなみに勉強会中はキャッシュ無しの方が速いという結果がでたが、それはもともとPCに入っていたRubyと新たにいれたRubyを比較した時の結果だった。今回は両方新たにいれたRubyを使用した。バージョンや、最適化の具合の違いではなかろうかと思う)