無駄なProcオブジェクトは作らないようにしよう
Procを凍結できないかなぁ、と思いつつRHGを読んでいて気がついたこと。
Procオブジェクトの生成はかなり重い処理になる。Procオブジェクトを作るには、
- マシンスタックに置いていたものを全部ヒープに移す
- POPされても回収されないようにする
である。ここで、「全部」というのはprevまで含めて全部だ。そこに積んであ るスタックフレームを全部malloc()してコピーして複製を作る。VARSは普通だ とPOPと同時にrb_gc_force_recycle()で強制回収されるのだが、それも DVAR_DONT_RECYCLEフラグを付けて停止させる。などなどだ。実に思いきったことをする。
という処理を行う必要がある。
一方イテレータでは、この処理は必要ない。
だから、
def f() yield 42 end
は
def g(&block) block.call 42 end
よりも軽いことになる。
100,000回ループさせたところ、前者は0.4秒、後者は0.9秒だったのでだいたい倍近く違うことになる。
まあ、誤差の範囲で片付けられる程度だけれど、一応心に止めておこう。