なぜRubyはメソッド呼び出しループベンチでかくも異常に遅いのか

476 :デフォルトの名無しさん:2011/02/25(金) 16:29:14.06
>>226 MatzRubyが堂々の3時間01分をたたき出したのには吹いた。
(趣味だけど)Ruby使いなんで、ちょっと擁護します
RubyのC実装(MatzRubyあるいはMRI)では速度とメモリ節約のために
31bitまでの整数を特別扱い(埋め込みオブジェクト)のFixnumとして
それを超えると多倍長整数のBignum(普通のオブジェクト)として扱ってます
よって2^31回ループさせるとFixnumの範囲を超えてしまうので遅くなります
ループ回数を半分に減らして 2^30回にするとFixnumの範囲内に収まるので速くなり
今回のベンチの実行時間では1/4ほどになります
64bit版MatzRubyだと、2^31回でもFixnumに収まるらしいです(63bitまでがFixnumなのかな)

【Perl,PHP】LLバトルロワイヤル15【Ruby,Python】


ほむ。

ということは、同じことが Smalltalk にも起こりうるわけで、ならばと調べてみたところ果たして Squeak の SmallInteger(Rubyなどで言うところの Fixnum に相当)の最大値(SmallInteger maxVal)は 3FFFFFFF、つまり 2^30 未満で、たしかに 7FFFFFFF のループではパフォーマンスが著しく低下するのもうなずける結果となりました。暗黙のうちに多倍長整数になってしまう動的な LL のループベンチでは気をつけなければいけない危険な落とし穴みたいですね。

正直なところ、Smalltalk 関連に限れば、id:uncorrelated さんのところのベンチ結果にはいささか納得がいっておらず、なるほどこうしたカラクリがあったのかとあたらめて合点がいった次第です。当方の測定では、MacBook Air が遅いからと FFFFFFF 回に減らしたのため、この落とし穴を回避できていたわけですね。

期待の Cog VM があまりに遅いとガッカリしていたのですが、むしろなかなか健闘しているじゃないかと逆に褒めてあげないといけないのかもしれません。^^;


参考: Cog Blog :: Build me a JIT as fast as you can…