VRエンジン作成日記

ひたすらVRエンジンを作っていきます

実行速度を最適化した

実行速度を最適化した。JavaScriptでは、C言語だとコンパイラが最適化してくれそうな箇所で最適化が入らなかったりする。最適化の一般的なお話でいうと、次のような項目は効果があると言えそう。

・関数のインライン展開

・複数回参照される項目を変数にキャッシュ

 (getterを見落としやすい)

・新しいオブジェクトを極力作らない

 (何らかの操作を行うメソッド内でnewされる箇所を見落としやすい)

・ループの展開

今のところ、ループの展開以外のものは心当たりがあったので、細かく最適化を入れていった。JavaScriptのコードはタスクマネージャで見てもCPU負荷に揺れがあるので、数値を見て最適化を実感することが難しかった。いくつもの内容を積み上げた結果、0.x%速くなったというようなことを繰り返した。CPU負荷に揺れがあるのは、JITの入るタイミングが不明、GCの動くタイミングが不明という2つが主な原因だと思う。

手書きで最適化する余地が多いのは、JavaScriptが動的な型付け言語だからだと言えそう。コンパイル時に変数の中に何が入っているのか分からない状態では、コンパイラJITの最適化に限界があるんだと思う。

今回、getter/setterの中身が簡単な場合でも、関数呼び出しと同じ負荷がかかってそうだというのを発見した。また、ベンチマーク用の関数を書いて2つの処理負荷を比べようと考えた時に、A → Bの順番で関数を呼び出した場合と、B → Aの順番で関数を呼び出した場合ではA、Bそれぞれの速度が変わってしまうというのも発見した。2つの位置をコピペで入れ替えて再度測ってみて、どちらの場合でもAが速いと言えないと、Aが実際に速いのかどうか分からない。これは盲点になりそうだ。あと、モダンなJavaScript限定のお話だけど、constを使うよりもvarの方がアクセスが速そうだった。これは確信を持ってそうだと言えるわけではないけど、数を積み重ねるとconstは処理が重くなっていく原因になっているように思える。

Webインスペクタの画面でパフォーマンスタブを開くと、メソッド1つ単位で処理負荷が見れるので、何度もリロードしては眺めて処理負荷を確認した。

UnitTestも揃っていない状態で最適化を入れたせいか、いくつか動きがおかしくなってしまったようだ。

・関連するコミット

optimize run speed · hikipuro/tea.js@38593fc · GitHub