コンピュータサイエンスにおいて、事前コンパイル(AOTコンパイル)とは、プログラムの実行前に(多くの場合)高水準のプログラミング言語を(多くの場合)低水準の言語にコンパイルする行為であり、通常はビルド時に行われ、実行時に実行する必要のある作業量を削減します。
これは、CやC++などの高水準プログラミング言語、あるいはJavaバイトコードやCIL(Common Intermediate Language )コードなどの中間表現をネイティブマシンコードにコンパイルし、結果として得られるバイナリファイルが標準的なネイティブコンパイラと同様にネイティブに実行できるようにする処理と最も一般的に関連付けられています。この文脈で使用される場合、これはしばしばジャストインタイム(JIT)コンパイルの対義語とみなされます。
より一般的に言えば、AOT コンパイルのターゲット言語は必ずしもネイティブマシン コードに特化しているわけではなく、かなり恣意的に定義されています。一部の学術論文では、この用語をJava バイトコードをC にコンパイルする行為[ 1 ]または最適化パイプラインが実行されるタイミング[ 2 ]を意味するために使用しています。ある学術プロジェクト[ 3 ]では、この用語をV8 (JavaScript エンジン)用のマシン依存の最適化IR [ 4 ]とJavaScriptCore用のマシン非依存のバイトコードにJavaScript をプリコンパイルする行為を意味するために使用しています。[ 5 ]一部の産業用言語実装 ( Clojure [ 6 ]や Hermes JavaScript エンジン[ 7 ]など) では、この用語をソース言語を VM 固有のバイトコードにプリコンパイルする行為を意味するために使用しています。Angular (ウェブ フレームワーク)では、この用語をHTMLテンプレートとTypeScriptをJavaScriptに変換することを意味するために使用しています。[ 8 ]
実際、静的コンパイルはすべて技術的には事前に実行されるため、この表現は、事前コンパイルよりもパフォーマンスが大幅に向上する例を強調するためによく用いられます。したがって、 JavaをJavaバイトコードにコンパイルする処理は、最適化ではなく要件であるため、AOTと呼ばれることはほとんどありません。
マネージドコードランタイムを備え、中間表現にコンパイルできるプログラミング言語の中には、ジャストインタイム(JIT)コンパイルを使用するものがあります。これは、中間コードの実行中に、中間コードをネイティブ実行用のマシンコードに短時間コンパイルするため、アプリケーションのパフォーマンスが低下する可能性があります。事前コンパイルは、実行中ではなく実行前にコンパイルを行うため、このステップが不要になります。
動的型付け言語をネイティブマシンコードまたはその他の静的VMバイトコードに事前コンパイルできるのは、限られたケースに限られます。例えば、Erlang言語用のHigh Performance Erlang Project (HiPE) AOTコンパイラは、高度な静的型再構築技術と型推測のおかげで、これを実現できます。
AOTコンパイルされたプログラムやライブラリを使用する場合、ほとんどの場合、ランタイム環境の一部を削除できるため、ディスク容量、メモリ、バッテリー寿命、起動時間(JITウォームアップフェーズが不要)などを節約できます。そのため、組み込み機器やモバイル機器で役立ちます。
AOTコンパイラは、JITコンパイルではほとんどの場合コストが高すぎると考えられるような、複雑で高度なコード最適化を実行できます。一方、AOTは通常、ランタイムプロファイルガイド最適化(PGO)、擬似定数伝播、間接仮想関数インライン化など、JITで可能な一部の最適化を実行できません。AOTはターゲットアーキテクチャに合わせてコンパイルする必要がありますが、JITはソフトウェアがリリースされてから何年も経っていても、実際に実行されているCPUを最大限に活用できるようにコードをコンパイルできます。
さらに、JITコンパイラはコードに関する仮定に基づいて、ホットコードを投機的に最適化できます。投機的な仮定が後で誤りであることが判明した場合、生成されたコードは最適化解除される可能性があります。このような操作は、適応型最適化によってコードが再び最適化されるまで、実行中のソフトウェアのパフォーマンスを低下させます。AOTコンパイラはこのような仮定を立てることができず、コンパイル時に可能な限り多くの情報を推論する必要があります。メソッドを通過する型がわからないため、より特殊化されていないコードに頼らざるを得ません。このような問題は、プロファイル誘導型最適化によって軽減できます。しかし、この場合でも、生成されたコードはJITコンパイラのように、変化するランタイムプロファイルに動的に適応させることはできません。