Gauche:LazyCompilation

Gauche:LazyCompilation

Gauche:VMの最適化から分岐。

動機

(2005/05/18 16:13:34 PDT) 0.8.4からGaucheのコンパイラはSchemeで記述され、より複雑な最適化を かけるようになっている。これはコンパイルされたプログラムそのものの 実行速度で倍近い改善をもたらしたが、一方コンパイル時間そのものが 倍近くになってしまった。起動の度にプログラムをコンパイルする スクリプトインタプリタとしてはコンパイル時間の増大は嬉しくない。

0.8.4のコンパイラは3パスなので。例えばロード時にPass1だけ走らせて おいて、コンパイルの残りは本当にそのコードが実行される時にやったら どうか、というのを思いつく。(選択肢としてはPass1も遅延させるというのも ありだが、コンパイル時に若干のエラーチェックは出来たらしておきたい。)

ひとつ、問題として考えられるのはマルチスレッド環境で、このようにコンパイルを 遅延させた場合、複数のスレッドが同じコードの遅延コンパイルに突入する 可能性がある。現在のコンパイラはPass1で作った構造をPass2で破壊的に 変更している部分があるのでまずい。アイディアとしてはこんなものがある。

測ってみる

戦略を見極めるにはデータが必要。ということで、色々測ってみる。

まず、各パスでどのくらいのリソースを喰ってるか。 ありったけのSchemeモジュールを読むだけのダミープログラムを作って、 プローブを仕込んで測って見たらこうなった。それぞれ、 一回のトップレベルフォームのコンパイルの平均値である。

pass1  time 318.634 us ( 58.0%)   alloc 5733.92 bytes ( 60.1%)
pass2  time  74.770 us ( 13.6%)   alloc 1248.62 bytes ( 13.1%)
pass3  time 155.766 us ( 28.4%)   alloc 2550.90 bytes ( 26.8%)

うーむ、実は最適化パスであるPass 2が一番重いんじゃないかと 思っていたんだが、意外にPass 1が重かった。Pass 1なんてS式から 内部構造を作ってるだけなのに。あいや、変数の束縛解決とマクロ展開も やってるか。アロケーションの配分と時間配分が綺麗に揃っているんで、 アロケーションが結構重いのかもしれぬ。

Pass 1で6割喰ってるってことは、遅延コンパイルを実装したとしても そこが限界ってことだよなあ。遅延コンパイル自体のオーバヘッドも あり得るし。

遅延コンパイルの導入による複雑化と天秤にかけると、もっとPass 1の 最適化を進める方がメリットが高そうだ。ということでこちらはしばらく凍結。


Last modified : 2012/02/02 11:54:49 UTC