バイトコード最適化プログラムの調査(その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)

遅くなってしまいました(涙)。

ローカル変数の参照はかなり速い(少なくともスタック操作と同等かそれ以上)ことが分かりました。
(ネタがあれば) つづく