バイトコード最適化プログラムの調査(その1)
前に書いた(http://d.hatena.ne.jp/miura1729/20080217/1203242232)バイトコードの最適化プログラムの為の調査をやってみました。
フィボナッチ級数のバイトコードを出力して、それを手で最適化するという方法で行いました。
def fib(n) if n < 2 then 1 else fib(n - 1) + fib(n - 2) end end
これをRubyコンパイラは次のようなバイトコードにコンパイルします。
2, [:getlocal, 2], [:putobject, 2], [:opt_lt], [:branchunless, :label_11], 3, [:putobject, 1], 2, [:leave], :label_11, 5, [:putnil], [:getlocal, 2], [:putobject, 1], [:opt_minus], [:send, :fib, 1, nil, 8, nil], [:putnil], [:getlocal, 2], [:putobject, 2], [:opt_minus], [:send, :fib, 1, nil, 8, nil], [:opt_plus], [:leave]
これを、次のように変数参照を減らし、出来る限りスタック操作のみで行うようにしました。
2, [:getlocal, 2], [:putobject, 2], [:opt_lt], [:branchunless, :label_11], 3, [:putobject, 1], 2, [:leave], :label_11, 5, [:getlocal, 2], [:dup], [:putnil], [:swap], [:putobject, 1], [:opt_minus], [:send, :fib, 1, nil, 8, nil], [:swap], [:putnil], [:swap], [:putobject, 2], [:opt_minus], [:send, :fib, 1, nil, 8, nil], [:opt_plus], [:leave]
結果です。fib(34)の実行速度です。
変更前
user system total real 3.656000 0.000000 3.656000 ( 3.676000)
変更後
user system total real 5.532000 0.000000 5.532000 ( 5.532000)
遅くなってしまいました(涙)。
ローカル変数の参照はかなり速い(少なくともスタック操作と同等かそれ以上)ことが分かりました。
(ネタがあれば) つづく