計測 & トライ - Scheme VM を書く

さて未だに「何をどう変えたら、どのくらい速くなるか?」などの感覚は得ることは出来ていませんが、計測の重要さは分かってきました。
そこでベンチマークスクリプトを書いて簡単に計測結果を日記貼り用出力に変換するところまで面倒を見ることにしました。
複数回ベンチマークを走らせて平均をとるなどもそいつがやります。


前回の計測から特に PUSH, CONSTANT, APPLY, REFER_FREE, REFER_LOCAL0 の命令たちが多く呼ばれていることが分かりました。
これらの命令が少しでも速くなれば全体の高速化につながるのではないかということでトライしてみます。
ここでは大きく構造を変更することはしません。

PUSH

PUSH を高速化するには?

    void push(Object obj)
    {
        if (sp_ >= stackSize_) {
            RAISE1("stack over flow sp=~d\n", Object::makeInt(sp_));
        }
        stack_[sp_++] = obj;
    }

スタックオーバーフローチェックを無くすことができれば多少速くなるかもしれません。
無くせるかはおいておいて、どの程度速度向上するか見てみましょう。

benchmark sec
./bench/fib.scm 0.091
./bench/case.scm 0.417
./bench/let.scm 0.080
./bench/tak.scm 0.061
./bench/decode.scm 0.030

benchmark sec
./bench/fib.scm 0.080
./bench/case.scm 0.400
./bench/let.scm 0.081
./bench/tak.scm 0.061
./bench/decode.scm 0.027


効果ありますね。これは測って良かった。これくらいのコード削除でこれだけ変わるのか。
さて方針としては 3 つくらいあるかな。

  • ユーザーフレンドリーさを考え今まで通りチェックする
  • 可能であればコンパイル時にスタックオーバーフローを起こすかを解析する。(大変そう)
  • スタックのサイズを大きめにする。デバッグビルド時だけスタックオーバーフローをチェック。

うーん。保留にしよう。

CONSTANT

簡単な最適化の余地はなさそうでした。

REFER_FREE

(REFER_FREE n) の n が境界を超えていないかのチェックは省略しても良いと思うので省略。
コンパイラのバグでもないと境界は超えないのでデバッグビルドのときだけチェックするようにした。
速度は全く向上せず。PUSH ほどの回数では実行されていないからかな?

REFER_LOCAL, REFER_LOCAL0

スタック参照するだけなので余地がなかった。

APPLY

APPLY はコードが長いので最適化の余地がありそうです。
RETURN 命令列の生成を毎回するのではなくて初期化時に1回だけやるようにしてみましょう。

./scripts/bench.scm > /dev/null

benchmark sec
./bench/fib.scm 0.092
./bench/case.scm 0.434
./bench/let.scm 0.089
./bench/tak.scm 0.061
./bench/decode.scm 0.030

benchmark sec
./bench/fib.scm 0.090
./bench/case.scm 0.421
./bench/let.scm 0.081
./bench/tak.scm 0.061
./bench/decode.scm 0.027

全体的に速くなりました。

あとコードを読んでいて const つけ忘れが目立つのできっちりつけてみました。

benchmark sec
./bench/fib.scm 0.090
./bench/case.scm 0.405
./bench/let.scm 0.083
./bench/tak.scm 0.061
./bench/decode.scm 0.030

あまり変わりません。でもバグを見つけることができたので良しとします。

まとめ

VMループ内の不要コードの削除でどれくらいの速度向上があるかを知ることができました。
目標としている Gauche との速度差を考えるとそこまで大きな改善にはいたっていません。
後述の mumurik さんのブログにもありますが目標値に向かってどのように改善されているかをグラフにしてみるのも良いかもしれません。
というかそうしよう。