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を使用した。バージョンや、最適化の具合の違いではなかろうかと思う)