JIT コンパイル

プログラムの実行時にコードをネイティブコードにコンパイルし、パフォーマンスを向上させる技術

ランタイムパフォーマンス

JIT コンパイルとは

JIT (Just-In-Time) コンパイルは、プログラムの実行時にバイトコードをネイティブコード (機械語) にコンパイルし、パフォーマンスを向上させる技術である。V8 (Node.js)、JVM (Java)、.NET CLR が JIT を使用する。

インタプリタ vs JIT vs AOT

方式 コンパイル時期 速度
インタプリタ 実行時に逐次解釈 遅い Python (CPython)
JIT 実行時にコンパイル 速い V8, JVM
AOT 事前にコンパイル 最速 Rust, Go, GraalVM

V8 の JIT パイプライン

JavaScript ソースコード
  ↓ パース
AST (抽象構文木)
  ↓ Ignition (インタプリタ)
バイトコード → 実行 (初回は遅い)
  ↓ ホットコードを検出
TurboFan (最適化 JIT コンパイラ)
  ↓ 最適化されたネイティブコード → 実行 (高速)
コンポーネント 役割
Ignition バイトコードインタプリタ (起動が速い)
TurboFan 最適化 JIT コンパイラ (実行が速い)

最適化と脱最適化

function add(a, b) { return a + b; }

// 最初の 100 回: a, b が常に number → TurboFan が number 専用コードを生成
add(1, 2);  // 高速 (最適化済み)

// 突然 string を渡す → 最適化が無効化 (脱最適化)
add("hello", "world");  // 遅い (インタプリタに戻る)

これが「単相性 (Monomorphism)」の重要性。同じ型を渡し続けると JIT が最適化できる。

Lambda でのコールドスタートと JIT

コールドスタート:
  1. 実行環境の初期化
  2. コードのロード
  3. JIT コンパイル (初回は遅い)
  → 初回リクエストのレイテンシが増加

ウォームスタート:
  1. JIT コンパイル済みコードを再利用
  → 高速

SnapStart (Java Lambda)

Java Lambda の JIT コンパイル済み状態をスナップショットとして保存し、コールドスタートを高速化する。

AOT との比較

観点 JIT (V8, JVM) AOT (Rust, Go)
起動速度 遅い (コンパイルが必要) 速い (コンパイル済み)
実行速度 高い (実行時最適化) 高い
メモリ 多い (コンパイラを含む) 少ない
Lambda 適性 コールドスタートが課題 コールドスタートが速い

さらに掘り下げるなら関連書籍が参考になる。

関連用語