by keigoi
http://d.hatena.ne.jp/keigoi/20101101/1288584308
ocamljs あとでパッチおくる †
- 現時点のocamljsでは関数呼び出しのオーバーヘッドがかなりある
- 関数のカリー化や末尾呼び出しの最適化のため関数呼び出し1回につき2回の間接ジャンプがある(コールスタックが3倍に伸びる)
- 通常のPCでは全く問題ない。スマートフォンでもユーザとのインタラクションに影響があるほどではないが、数値計算などで扱うデータの量が多い場合には注意が必要(経験談)
- 生成されるJavaScript?は元のOCamlコードの原型が残っているので、Google Closure Compilerによる圧縮と併せて理想的なJavaScript?に落ちるようなOCamlの書き方を探すこともできる
- 特にモジュールをまたいだ呼び出しが最適化されないためListやArrayモジュールのほとんどが低速。効率化するならばまずmap/fold系の高階関数をやめfor式を使い、配列のアクセスを Array.unsafe_get / unsafe_set に置き換えるか、 a.(i)記法を使うならばoc$arefの境界チェックを外してclosure compilerで最適化する。
- このような最適化をプロファイルの後にごく一部で行うだけで劇的に改善できる。どうしても駄目なときはインラインJavaScript? << ... >> を使う。 型がないので注意
多相的な比較は超低速 (.jsのcompare_valを見よ) †
- min, maxも多相的
- 奥義・多相転生を使う
- 要するにintやfloat等の型をつければそれ専用の比較が行われるようになる
- 使われていないモジュールはリンクされない。
- Printfはコードサイズを大きくしがち
- Randomを使うとInt64がついてくる
Google Closure Compilerによる 圧縮 †
- 以前はclosure compilerでSIMPLE_OPTIMIZATIONすると動かなかった(keigoiの日記参照)が修正された。
- closure compilerでADVANCED_OPTIMIZATIONすると動かないが、 出現する m.$oc などを m['$oc'] に置き換えれば動くようになる。 (未報告)
- ADVANCED_OPTIMIZATIONはいくらかdead code eliminationや簡単なインライン化もやってくれるので有用。
- ADVANCED_OPTIMIZATIONでは o.field 形式のフィールドアクセスにおけるフィールド名が全て o.a のように短縮されてしまうが、 o['field'] のように文字列にすれば短縮されない。詳しくはclosure compilerのページ参照
- ocamljsの進化により無効になるテクニックや、そもそも根拠があいまいなものなど
- ADVANCED_OPTIMIZATION前提
パターンマッチはclosure compilerで最適化されない †
(function(){ var x = ...; expr }());
などと余計な呼び出しが挿入される(が、最適化で除去されることも?)。