Skip to content
Latchkey

ahead-of-timeコンパイルとは? 実行前にコンパイルする

ahead-of-time (AOT) コンパイルは、プログラムの実行前にソースやbytecodeをネイティブのマシンコードへ翻訳するため、起動した瞬間にフルスピードに達します。

AOTコンパイルは古典的なモデルです。翻訳作業をすべてbuild中に行い、すぐ実行できるバイナリを出荷し、コンパイルのために実行時には何も払いません。C、Rust、Goのような言語はデフォルトでAOTであり、通常はJITするruntime (.NETなど) も、より速い起動と小さいフットプリントのためにAOTモードを提供することが増えています。

AOTの仕組み

build中に、コンパイラはすべてをターゲットアーキテクチャのネイティブ命令へ翻訳し、runtimeデータなしで最適化します。出力はCPUが直接実行する自己完結した実行可能ファイルで、プログラムの実行中にコンパイルは一切起きません。

AOT vs JIT

JITは実行時にコンパイルし、ライブのプロファイリングを使って最適化できますが、ウォームアップのコストを払います。AOTは即座のピーク速度と予測可能な起動のために前もってコンパイルしますが、runtimeの振る舞いに適応できません。多くのモダンなruntimeは、どちらかを選ばせてくれます。

AOTが輝くとき

  • JITをウォームアップするほど長く生きない、短命なプロセス。
  • cold startのレイテンシが重要な、serverlessやCLIツール。
  • JITコンパイラのオーバーヘッドが大きすぎる、制約された環境。
  • 最初の命令から予測可能で再現性のある性能。

トレードオフ

AOTのバイナリは起動が速く予測可能に振る舞いますが、ターゲットアーキテクチャに縛られ、JITが実際のワークロードから行える適応的な最適化を逃します。また、コンパイルのコストを実行時ではなくbuildで払います。

簡単な例

go build を実行すると、ネイティブなバイナリが前もって生成されます。それを実行するとき、コンパイル段階もウォームアップもありません。プログラムは即座にフルスピードで動きます。

CIにおけるAOT

AOTはコストをbuildへ移すため、コンパイルがpipelineの時間を支配し、CPUとメモリに負荷をかけることがあります。複数のアーキテクチャ向けのクロスコンパイルはこれを倍増させます。より大きなrunner (Latchkey) はAOTのbuildを高速化し、コンパイル中の一時的なtoolchainやOOMの失敗は自動でリトライできます。

重要なポイント

  • AOTはruntimeの前にネイティブコードへコンパイルするため、プログラムは即座にフルスピードで動きます。
  • 短命なプロセスやcold startに敏感なワークロードでは、JITに勝ります。
  • コンパイルのコストがbuildへ移るため、AOTのbuildはCPUとメモリを多く使います。

関連ガイド