ホットスポットを最適化する

最適化するのに相応しいサブルーチンのみ最適化できるように,optimizer::hotspotというモジュールを考えてみた。まだCPANクオリティではないのでgithubのみ。

仕組みとしては,PL_peeppをフックして,生成されるサブルーチンの頭にホットスポット計測のためのopcode*1を仕込み,そのopcodeが一定数呼ばれると,最適化器*2を起動するというものだ。

最適化の基本は,いまのところ特定パターンをもつ構文木を高速な一つのノードに置き換えるというもの。少し実装してみたところ,以下のような結果となった。
benchmarks/arbit.pl

# 's' represents 'single-threaded'
$ sperl -Mblib benchmarks/arbit.pl
Perl/5.10.1 on i686-linux
           Rate     plain optimized
plain     489/s        --      -39%
optimized 797/s       63%        --

以上,Perlを63%高速化することができた。

.
.
.

もちろん,これで済むほど話は簡単ではない。このベンチマークは恣意的なもので,ベンチマークスクリプトは非常に不自然なコードである。もう少しまともなbenchmark/math.plを実行すると,効果は誤差の範囲内でしかないことがわかる。
ホットスポットを検出して最適化器を起動する,というところまではいいが,そこから先の最適化についてはもう少しいい方法を考えないと使い物にならないのではないかと思う。
特定パターンを検出する方法は,まずパターンの検出が大変すぎるし,この調子でパターンを増やしたとしても所詮ヒューリスティクスによる小手先の最適化にすぎず,アプリケーションレベルで+10%達成できれば御の字だろう。
ということを考えると,プロファイラでボトルネックを探してその部分をXS化するほうがずっと簡単だ。

*1:対応するppcodeはoptimizer_pp_count()

*2:optimizer_hotspot_peep() -> optimizer_combine_opcode()