JIT コンパイル
プログラムの実行時にコードをネイティブコードにコンパイルし、パフォーマンスを向上させる技術
JIT コンパイルとは
JIT (Just-In-Time) コンパイルは、プログラムの実行時にバイトコードをネイティブコード (機械語) にコンパイルし、パフォーマンスを向上させる技術である。V8 (Node.js)、JVM (Java)、.NET CLR が JIT を使用する。
インタプリタ vs JIT vs AOT
インタプリタと JIT vs AOT の違いを以下にまとめる。
| 方式 | コンパイル時期 | 速度 | 例 |
|---|---|---|---|
| インタプリタ | 実行時に逐次解釈 | 起動は速いが実行は遅い | Python (CPython) |
| JIT | 実行時にコンパイル | 起動は遅いが実行は速い | V8, JVM |
| AOT | 事前にコンパイル | 起動も実行も速い (実行時の最適化は無い) | Rust, Go, GraalVM |
V8 の JIT パイプライン
V8 の JIT パイプラインを図で示す。
JavaScript ソースコード
↓ パース
AST (抽象構文木)
↓ Ignition (インタプリタ)
バイトコード → 実行 (起動は速いが実行は遅い)
↓ 何度か呼ばれたら
Sparkplug (ベースラインコンパイラ)
↓ さらに呼ばれ、扱う型が安定していたら
Maglev (中位の最適化コンパイラ)
↓ ホットコードとして残り続けたら
TurboFan (最上位の最適化コンパイラ)
→ 最適化されたネイティブコード → 実行 (高速)
| コンポーネント | 役割 |
|---|---|
| Ignition | バイトコードインタプリタ (起動が速い) |
| Sparkplug | 最適化を省いたベースラインコンパイラ (2021 年の V8 v9.1 で追加) |
| Maglev | 中位の最適化コンパイラ (Chrome 117 で追加) |
| TurboFan | ピーク性能を狙う最適化コンパイラ (実行が速い) |
段が増えたのは、起動の速さとピーク性能のどちらかを捨てずに済ませるためである。1 度しか呼ばれない関数に TurboFan の最適化時間を払うのは損で、逆にループの中心にある関数をインタプリタで回し続けるのも損になる。V8 は呼び出し回数と型の安定度を見ながらコードを上の段へ昇格させる。Ignition と TurboFan の 2 段だけという解説も広く流通しているが、間の 2 段が入ったのは 2021 年 (Sparkplug) と 2023 年 (Maglev) である。
最適化と脱最適化
最適化と脱最適化のコード例を示す。
function add(a, b) { return a + b; }
// 何度も呼ばれ、a, b が常に number → 型を number と決め打ちしたコードが生成される
add(1, 2); // 高速 (最適化済み)
// 突然 string を渡す → 決め打ちが崩れて最適化コードが破棄される (脱最適化)
add("hello", "world"); // 遅い (バイトコードの実行に巻き戻る)
これが単相性 (monomorphism) が効く理由である。同じ型・同じ形のオブジェクトだけが渡される呼び出し箇所なら、JIT は型の判定を省いた短いコードを吐ける。渡される型が数種類に増えると判定の分岐が入り、種類が多すぎると最適化を諦めて汎用の呼び出しに落ちる。
実務上の指針は 2 つに絞れる。1 つの引数に数値も文字列も配列も来る関数を作らないこと、同じ役割のオブジェクトはプロパティの追加順まで揃えて生成することである。ただしこれが意味を持つのはホットループの中だけで、毎秒数回しか通らないコードで型を揃える労力を払う価値はない。
Lambda でのコールドスタートと JIT
コールドスタート:
1. 実行環境の初期化
2. コードのロード
3. JIT コンパイル (初回は遅い)
→ 初回リクエストのレイテンシが増加
ウォームスタート:
1. JIT コンパイル済みコードを再利用
→ 高速
SnapStart
初期化フェーズを終えた実行環境のメモリとディスクの状態を Firecracker microVM のスナップショットとして保存しておき、以降の呼び出しではそこから復元することでコールドスタートを縮める仕組みである。初期化の途中で行われた JIT コンパイルの結果もメモリ状態の一部として保存されるため、実行時コンパイルを前提とするランタイムほど効きが大きい。
2026 年 8 月時点で使えるのはマネージドランタイムの Java 11 以降、Python 3.12 以降、.NET 8 以降で、コンテナイメージでは使えない。有効にできるのは発行済みのバージョンとそれを指すエイリアスだけで、$LATEST では使えない点も設計時に押さえておく。
AOT との比較
AOT との主な違いを以下に比較する。
| 観点 | JIT (V8, JVM) | AOT (Rust, Go) |
|---|---|---|
| 起動速度 | 遅い (コンパイルが必要) | 速い (コンパイル済み) |
| 実行速度 | 高い (実行時の型情報による投機的最適化が効く) | 高い (実行時の情報は使えない) |
| メモリ | 多い (コンパイラを含む) | 少ない |
| Lambda 適性 | コールドスタートが課題 | コールドスタートが速い |
さらに掘り下げるなら関連書籍が参考になる。
この記事は役に立ちましたか?
関連用語
関連する記事
OS / 低レイヤー本ガイド - コンピュータの仕組みを学ぶ技術書の選び方
OS、コンパイラ、ネットワークなど低レイヤーを学べる技術書の 4 ジャンルと、どこから始めるべきかの指針、賞味期限の見極め方を紹介します。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。
スマホ / パソコン入門書の選び方 - シニアの家族に贈る 1 冊の見つけ方
スマホとパソコンの入門書を「贈る側 / 教える側」の視点で選ぶガイド。機種と OS の一致、文字の大きさ、年度の確認という 3 条件と、Android / iPhone / Windows 11 それぞれの定番書、安全対策の 1 冊まで 2026 年 8 月時点の収載書から紹介します。