コンパイラ・インタプリタ・JITの違い:実行方式を比較

ソースコードを実行する方法は、主に3つあります。コンパイラ(事前コンパイル、AOT)は、プログラムの実行前に、全体を機械語に変換します。インタプリタは、機械語のファイルを作らずに、実行しながらプログラムを読んで動かします。JITコンパイラ(ジャストインタイム)は、まずインタプリタで始め、よく使う部分を、プログラムの実行中に機械語へコンパイルします。多くの言語が、これらを組み合わせています。

項目コンパイラ(AOT)インタプリタJITコンパイラ
変換する時期実行前。プログラム全体が機械語になる実行中。プログラムを読みながら、1ステップずつ動かす実行中。よく使うコードを機械語にコンパイルする
起動速く始まる(ただし先にビルドが必要)速く始まる。ビルドは不要最初は遅い。コードが温まる(ウォームアップ)まで
実行速度最も速く、予測しやすい最も遅い。コンパイルしたコードの何倍も遅いことが多いウォームアップ後はコンパイルした速度に近く、実行時の情報を使って、速くなることもある
移植性プラットフォームごとにバイナリが必要移植しやすい。インタプリタがある場所なら動く移植しやすいバイトコードと、プラットフォームごとのランタイム
エラーの検出多くのエラーをコンパイル時に見つけられる問題のある行が実行されたときにエラーが出る言語による
メモリの使用量実行時の負荷が小さいインタプリタ自体がメモリに常駐するコンパイラと、コンパイル済みコードのキャッシュのために、メモリが余分に要る
開発の流れ編集、ビルド、実行編集してすぐ実行多くは編集して実行、またはバイトコードへビルド
代表的な言語C、C++、Rust、Go従来のPython(CPython)、Ruby、シェルスクリプトJava(HotSpot)、JavaScript(V8)、C#(.NET)、PyPy

数値は代表的な目安で、世代や製品によって異なります。

どんなときに使うか

コンパイラ
性能、小ささ、予測しやすい動作が重要なとき。OS、ゲーム、組み込みのファームウェアなど。
インタプリタ
手早い実験、スクリプト、学習など、速度よりも開発の速さが重要なとき。
JIT
移植しやすいプラットフォームで、長く動くプログラムに速度が必要なとき。ウェブブラウザやサーバーのアプリケーションなど。

よくある質問

Pythonはコンパイル型ですか、インタプリタ型ですか?

標準の実装であるCPythonは、ソースコードをバイトコードにコンパイルし、それをインタプリタで実行します。PyPyなどのほかの実装は、JITコンパイラを加えて、より速くしています。

Javaはコンパイル型ですか、インタプリタ型ですか?

両方です。Javaは、事前にバイトコードへコンパイルされ、それをJVMが、プログラムの実行中にインタプリタで動かしたり、JITで機械語へコンパイルしたりします。

なぜコンパイルしたコードは速いのですか?

プログラム全体が、実行前に最適化された機械語に変換されるので、実行時に解釈する必要がないからです。

JITコンパイラのウォームアップとは何ですか?

最初は、プログラムをインタプリタで動かし、よく実行されるコードを見つけてから、JITがコンパイルします。それまでは、速度が低めです。

理解度チェック

コンパイラとインタプリタの違いとして正しいものはどれか。

  1. Aコンパイラは実行前に翻訳し、インタプリタは読みながら実行する
  2. Bコンパイラは実行しながら1行ずつ翻訳し、インタプリタは実行前にまとめて翻訳する
  3. Cコンパイラは数値計算だけ、インタプリタは文字の処理だけを扱う
答えと解説を見る

正解:A. コンパイラは実行前に翻訳し、インタプリタは読みながら実行する

コンパイラはプログラム全体を実行する前に機械語などに翻訳し、翻訳した結果を実行します。翻訳に時間がかかる代わりに、実行は速くなり、最適化にも時間をかけられます。インタプリタはプログラムを読みながら解釈して実行するので、すぐ試せる一方、実行は遅くなりがちです。実際にはバイトコードに翻訳してから解釈し、よく使う部分をJITコンパイルするなど、両者を組み合わせた方式も多く使われます。扱える処理の種類で分けるわけではありません。

JITコンパイルを使う実行環境の特徴として正しいものはどれか。

  1. Aプログラムを実行する前に、すべてを機械語に翻訳してから配布する
  2. B実行中によく使う部分を機械語にし、実行時の情報も使える
  3. C機械語を一切使わず、いつまでもバイトコードを1命令ずつ解釈し続ける
答えと解説を見る

正解:B. 実行中によく使う部分を機械語にし、実行時の情報も使える

JITコンパイルでは、最初はバイトコードを解釈しながら実行し、何度も実行される部分(ホットスポット)を見つけたら、実行中にそこを機械語にコンパイルします。実際に通る分岐や渡される型などの実行時の情報を使って、前もって行うコンパイルでは難しい大胆な最適化ができます。想定が外れたら解釈の実行に戻るしくみも備えています。前もってすべてを翻訳するのは事前(AOT)コンパイル、解釈だけを続けるのは純粋なインタプリタです。

コンパイラの内部で、ソース言語にもCPUにも依存しない中間表現(IR)を使う主な利点はどれか。

  1. A中間表現を使うと、ソースコードを読まずにコンパイルできるようになるから
  2. B中間表現はCPUがそのまま実行できるので、機械語の生成が不要になるから
  3. C言語ごとの前半とCPUごとの後半を分けられ、最適化も共通に使えるから
答えと解説を見る

正解:C. 言語ごとの前半とCPUごとの後半を分けられ、最適化も共通に使えるから

M種類の言語とN種類のCPUに対応するとき、組み合わせごとにコンパイラを作るとM×N個必要ですが、共通の中間表現を介せば、言語から中間表現への前半(フロントエンド)M個と、中間表現からCPUへの後半(バックエンド)N個で済みます。最適化の多くも中間表現の上で一度作れば、すべての言語とCPUで使えます。中間表現はCPUがそのまま実行できるものではなく、最後に機械語へ変換する必要があります。

  1. コンパイラの字句解析の役割として正しいものはどれか。
  2. コンパイラの構文解析で行うこととして正しいものはどれか。

コンパイラの練習問題へ

関連する用語の解説

JITコンパイル
プログラムの実行中に、よく実行される部分を機械語にコンパイルする方式。実行時の情報を使った最適化ができる。JavaやJavaScriptの実行環境などで使われる。

関連する比較