JITコンパイル
実行時に機械語へコンパイルする。 Just-In-Time。
基本の考え方#
プログラムの実行時間の大半は、 ごく一部のコード(ホットスポット)に費やされる。
そこだけを機械語にコンパイルすれば、 全体をコンパイルするコストを払わずに ほとんどの速度を得られる。
起動 → [[インタプリタ]]で実行(速く始まる)
→ 実行回数をカウント
→ しきい値を超えたら機械語にコンパイル
→ 以降は機械語で実行AOT に無い強み#
実行時の情報が使える。
| 情報 | 利用 |
|---|---|
| 実際に来る型 | 型特化したコードを生成 |
| 分岐の偏り | よく通る側を直線的に配置 |
| 呼ばれる実装 | 仮想呼び出しを直接呼び出しに |
| 実際の CPU | AVX-512 があれば使う |
動的型付け言語で JIT の効果が特に大きいのは、 「この変数は実際には常に整数」という情報が 静的には得られないため。
投機と脱最適化#
実行時の観測は未来の保証ではない。
「この関数はいつも整数を受け取る」と仮定してコンパイルし、 仮定を検査するガードを入れておく。 仮定が破れたら脱最適化してインタプリタに戻る。
この仕組みがあるから、 静的には不可能な最適化を安全に適用できる。
代償#
- 起動が遅い(ウォームアップ)
- コンパイラ自身のメモリと CPU を消費する
- 生成コードを置くため、実行可能なメモリが要る。 iOS はセキュリティ上これを制限しており、 サードパーティアプリで JIT が使えない
段階的コンパイル#
多くの処理系は複数段階を持つ。
インタプリタ → 簡易 JIT(速くコンパイル) → 最適化 JIT(時間をかける)V8 の Ignition / TurboFan、 JVM の C1 / C2 がこの構成。
参考文献#
- John Aycock. A brief history of just-in-time. ACM Computing Surveys 35(2), 2003. https://doi.org/10.1145/857076.857077
- Urs Hölzle, Craig Chambers, David Ungar. Debugging Optimized Code with Dynamic Deoptimization. PLDI, 1992. https://doi.org/10.1145/143095.143114
- Robert Nystrom. Crafting Interpreters. Genever Benning, 2021.(全文公開) https://craftinginterpreters.com/