| プログラムの実行 |
|---|
| 一般的な概念 |
| コードの種類 |
| コンパイル戦略 |
| 有名なランタイム |
|
| 有名なコンパイラとツールチェーン |
|
事前コンパイラ(Ahead-Of-Timeコンパイラ、AOTコンパイラ、英: ahead-of-time compiler)とは、アプリケーション実行前に(事前に)ソースコードや中間表現(中間言語)を機械語へ変換(コンパイル)するコンパイラのこと。対義語は実行時コンパイラ(Just-In-Timeコンパイラ、JITコンパイラ)。
概要
[編集]JITコンパイラはアプリケーションの実行直前または実行中に、中間言語コードを実行環境のプロセッサに応じた機械語コードにコンパイルするため、インタプリタによる逐次実行方式よりは高速であるものの、必要なコードがすべて機械語に変換されてメモリ上に展開され、定常状態に到達する(ウォームアップが完了する)まではアプリケーションの性能を低下させることがある。特に起動にかかる時間が増加するため、起動と終了を繰り返すアプリケーションで問題になることがある。AOTコンパイラは実行時コンパイルの必要性を無くし、ソースコードから中間言語コードを生成した後に、ネイティブの機械語コードを生成させる方式で性能低下を回避できる。JITコンパイラと区別するためAOTコンパイラという言葉が使われるが、C言語やC++など、AOTコンパイラが事実上の標準となっている言語では、わざわざAOTをつけずに単にコンパイラと呼ばれることがほとんどである。
AOTコンパイルは比較的高性能で潤沢な計算資源(高速なCPU、大容量のメモリやストレージなど)を搭載した開発環境において実行され、JITコンパイルよりも時間的・空間的リソースを費やして入念な最適化を実行できる余裕があり、またコンパイラに渡すオプションによって最適化レベルをアプリケーション開発者側で制御しやすい。ただし、AOTコンパイルしたコードが常にJITコンパイルしたコードよりも高速であるとは限らない。一般的にAOTコンパイラは事前に特定の命令セットを仮定し、ターゲット環境が必ずサポートする命令を使ってコードを生成するため、最適化性能はその制約を受けやすい。AOTコンパイルでSIMDのような拡張命令を利用して最適化する場合、拡張命令をサポートしない環境でもプログラムを実行できるようにするためには、個別にコードを分けて出力し、ファットバイナリのような形で提供しなければならず、実行ファイルのサイズ増大を招きやすい。一方、JITコンパイルは完全に実行環境に限定したコードのみを生成することができ、実行環境にとって最も効率のよいシンプルかつ高速なコード生成をしやすい[1]。
.NET
[編集]C#やVisual Basic .NETをはじめとする.NET言語は、JITコンパイル方式が基本ではあるが、もともと.NET Frameworkでは、マネージアセンブリから事前にネイティブコードを生成してインストールするツールとして「Ngen.exe (ネイティブ イメージ ジェネレーター)」をサポートしていた[2]。しかし、これは主に起動と終了を繰り返すことで蓄積されるオーバーヘッドが問題となるサーバーアプリケーション向けのソリューションであり、手軽に利用できるものではなく、また一部の動的な機能が利用できなくなるなどの欠点もある。このツールはJITコンパイラとともに、Windows 8.xのWindowsストアアプリでも使われていた[3]。Windows 10のUWPアプリケーションでは、「.NET Native」と呼ばれる類似の事前コンパイル技術がサポートされた[4]。
.NET Coreでは、バージョン3.0でAOTコンパイルの一種であるReadyToRun形式がサポートされた[5]。2022年末にリリースされた.NET 7ではネイティブAOTがサポートされたが、ネイティブAOTと完全に互換性のあるライブラリは限定されている[6]。
Java
[編集]GraalVM
[編集]GraalVMは、事前コンパイルしてネイティブイメージの作成ができる。アプリの起動時間が短くなる。起動時間が短くなることによりAWS Lambdaなどでの使用に適している。[7]
下記はJava 20現在の、GraalVM開発者によるSpring BootのPetClinicサンプルアプリによるベンチマーク結果。起動は圧倒的に速くなるが、処理速度はOpenJDKの方が速い。GraalVMはprofile-guided optimization (PGO)を使用し、コンパイル前に処理内容のプロファイリングをとってからコンパイルして、ガベージコレクタにはG1 GCを使用している。[8]
| OpenJDK | GraalVM | |
|---|---|---|
| 起動時間 | 7.18秒 | 0.22秒 |
| メモリ使用量 | 1,751MB | 694MB |
| 処理速度 | 12,800リクエスト/秒 | 10,249リクエスト/秒 |
OpenJDK
[編集]アプリの起動時間の短縮を目的に以下の機能が追加されている。JITコンパイルは処理に時間がかかるが、アプリを起動するたびに、毎回同じ処理を行うのは無駄であり、過去に行ったJITコンパイルの結果を保存する。[9]
脚注
[編集]- ↑ Javaの新JITコンパイラ、Graalを解説
- ↑ Ngen.exe (ネイティブ イメージ ジェネレーター) - .NET Framework | Microsoft Learn
- ↑ Migrating Your Windows 8.x App to .NET Native - UWP applications | Microsoft Learn
- ↑ .NET ネイティブによるアプリのコンパイル - UWP applications | Microsoft Learn
- ↑ What's new in .NET Core 3.0 | Microsoft Learn
- ↑ “Native AOT deployment overview - .NET”. Microsoft Learn. 2023年1月6日閲覧。
- ↑ “Native Image”. graalvm.org. 2025年10月31日閲覧。
- ↑ Yurenko, Alina. “A New GraalVM Release and New Free License!”. Medium. 2025年11月1日閲覧。
- ↑ “Project Leyden”. openjdk.org. 2025年10月31日閲覧。
- ↑ “JEP 483: Ahead-of-Time Class Loading & Linking”. openjdk.org. 2025年10月31日閲覧。
- ↑ “JEP 514: Ahead-of-Time Command-Line Ergonomics”. openjdk.org. 2025年10月31日閲覧。
- ↑ “JEP 515: Ahead-of-Time Method Profiling”. openjdk.org. 2025年10月31日閲覧。
- ↑ “JEP 516: Ahead-of-Time Object Caching with Any GC”. openjdk.org. 2025年10月31日閲覧。
- ↑ “JEP draft: Ahead-of-Time Code Compilation”. openjdk.org. 2025年10月31日閲覧。