事前コンパイラ

事前コンパイラ（Ahead-Of-Timeコンパイラ、AOTコンパイラ、）とは、アプリケーション実行前に（事前に）ソースコードや中間表現（中間言語）を機械語へ変換（コンパイル）するコンパイラのこと。対義語は実行時コンパイラ（Just-In-Timeコンパイラ、JITコンパイラ）。

 概要 
JITコンパイラはアプリケーションの実行直前または実行中に、中間言語コードを実行環境のプロセッサに応じた機械語コードにコンパイルするため、インタプリタによる逐次実行方式よりは高速であるものの、必要なコードがすべて機械語に変換されてメモリ上に展開され、定常状態に到達する（ウォームアップが完了する）まではアプリケーションの性能を低下させることがある。特に起動にかかる時間が増加するため、起動と終了を繰り返すアプリケーションで問題になることがある。AOTコンパイラは実行時コンパイルの必要性を無くし、ソースコードから中間言語コードを生成した後に、ネイティブの機械語コードを生成させる方式で性能低下を回避できる。JITコンパイラと区別するためAOTコンパイラという言葉が使われるが、C言語やC++など、AOTコンパイラが事実上の標準となっている言語では、わざわざAOTをつけずに単にコンパイラと呼ばれることがほとんどである。

AOTコンパイルは比較的高性能で潤沢な計算資源（高速なCPU、大容量のメモリやストレージなど）を搭載した開発環境において実行され、JITコンパイルよりも時間的・空間的リソースを費やして入念な最適化を実行できる余裕があり、またコンパイラに渡すオプションによって最適化レベルをアプリケーション開発者側で制御しやすい。ただし、AOTコンパイルしたコードが常にJITコンパイルしたコードよりも高速であるとは限らない。一般的にAOTコンパイラは事前に特定の命令セットを仮定し、ターゲット環境が必ずサポートする命令を使ってコードを生成するため、最適化性能はその制約を受けやすい。AOTコンパイルでSIMDのような拡張命令を利用して最適化する場合、拡張命令をサポートしない環境でもプログラムを実行できるようにするためには、個別にコードを分けて出力し、ファットバイナリのような形で提供しなければならず、実行ファイルのサイズ増大を招きやすい。一方、JITコンパイルは完全に実行環境に限定したコードのみを生成することができ、実行環境にとって最も効率のよいシンプルかつ高速なコード生成をしやすいJavaの新JITコンパイラ、Graalを解説。

 .NET 
C#やVisual Basic .NETをはじめとする.NET言語は、JITコンパイル方式が基本ではあるが、もともと.NET Frameworkでは、マネージアセンブリから事前にネイティブコードを生成してインストールするツールとして「Ngen.exe (ネイティブ イメージ ジェネレーター)」をサポートしていたNgen.exe (ネイティブ イメージ ジェネレーター) - .NET Framework | Microsoft Learn。しかし、これは主に起動と終了を繰り返すことで蓄積されるオーバーヘッドが問題となるサーバーアプリケーション向けのソリューションであり、手軽に利用できるものではなく、また一部の動的な機能が利用できなくなるなどの欠点もある。このツールはJITコンパイラとともに、Windows 8.xのWindowsストアアプリでも使われていたMigrating Your Windows 8.x App to .NET Native - UWP applications | Microsoft Learn。Windows 10のUWPアプリケーションでは、「.NET Native」と呼ばれる類似の事前コンパイル技術がサポートされた.NET ネイティブによるアプリのコンパイル - UWP applications | Microsoft Learn。

.NET Coreでは、バージョン3.0でAOTコンパイルの一種であるReadyToRun形式がサポートされたWhat's new in .NET Core 3.0 | Microsoft Learn。2022年末にリリースされた.NET 7ではネイティブAOTがサポートされたが、ネイティブAOTと完全に互換性のあるライブラリは限定されている。

 Java 
 GraalVM 
は、事前コンパイルしてネイティブイメージの作成ができる。アプリの起動時間が短くなる。起動時間が短くなることによりAWS Lambdaなどでの使用に適している。

下記はJava 20現在の、GraalVM開発者によるのPetClinicサンプルアプリによるベンチマーク結果。起動は圧倒的に速くなるが、処理速度はOpenJDKの方が速い。GraalVMはprofile-guided optimization (PGO)を使用し、コンパイル前に処理内容のプロファイリングをとってからコンパイルして、ガベージコレクタにはG1 GCを使用している。

  OpenJDK GraalVM 起動時間 7.18秒 0.22秒 メモリ使用量 1,751MB 694MB 処理速度 12,800リクエスト/秒 10,249リクエスト/秒

 OpenJDK 
アプリの起動時間の短縮を目的に以下の機能が追加されている。JITコンパイルは処理に時間がかかるが、アプリを起動するたびに、毎回同じ処理を行うのは無駄であり、過去に行ったJITコンパイルの結果を保存する。
 Java 24
 JEP 483: Ahead-of-Time Class Loading & Linking
 Java 25
 JEP 514: Ahead-of-Time Command-Line Ergonomics
 JEP 515: Ahead-of-Time Method Profiling
 Java 26
 JEP 516: Ahead-of-Time Object Caching with Any GC
 開発中
 JEP draft: Ahead-of-Time Code Compilation

 脚注 

 関連項目 
実行時コンパイラ
GNU Compiler for Java
JRuby
レトロニム

Category:コンパイラ