Graalコンパイラ

Graalコンパイラは動的なJust-in-Time (JIT)コンパイラで、Javaで記述され、バイトコードをマシン・コードに変換します。Graalコンパイラは、互換性のあるバージョンのJVMコンパイラ・インタフェース(JVMCI)をサポートするJava HotSpot VMと統合されています。JVMCIはJVMに対する権限のある低レベルのインタフェースであり、Javaで記述されたコンパイラをJVMで動的なコンパイラとして使用できるようにします(「JEP 243」を参照)。これにより、メソッドのバイトコードなどのメタデータをVMから読み取り、マシン・コードをVMにインストールできます。GraalVMには、JVMCIをサポートするHotSpot JVMのバージョンが含まれています。

コンパイラの利点

Graalコンパイラは、コード分析および最適化に対する独自のアプローチによって、JVMで実行されているプログラムのパフォーマンスを最適化します。これには、積極的なインライン化、多相インライン化など、複数の最適化アルゴリズム(フェーズと呼ばれる)が含まれています。たとえば、GraalVM Enterpriseのコンパイラには62の最適化フェーズが含まれ、そのうち27が特許を取得しています。

Graalコンパイラは、負荷のかかるオブジェクト割当てを排除できるため、高度に抽象化されたプログラムのパフォーマンス上の利点が確保されます。より抽象化され、ストリームやラムダなどの最新のJava機能を使用するコードでは、より大幅に速度が向上します。低レベルのコード、またはI/O、メモリー割当て、ガベージ・コレクションなどに収束するコードでは、改善の効果は小さくなります。このため、GraalVMで実行されるアプリケーションは、メモリー管理およびガベージ・コレクションに費やす時間を短縮する必要があります。パフォーマンス・チューニングの詳細は、「JVMでのコンパイラ構成」を参照してください。

グラフ・コンパイル

ゲスト・プログラミング言語、つまりJavaScript、Ruby、R、PythonおよびWebAssemblyをホストJVMベース言語と同じランタイムで実行するには、コンパイラは、ソース言語と生成されるマシン・コードの間で言語に依存しない中間表現(IR)を使用する必要があります。このロールにはグラフが選択されました。

グラフは、if文やループなど、異なる言語の類似した文を同じ方法で表すことができるため、同じプログラム内で言語を混在させることができます。これにより、Graalコンパイラは、言語に依存しない最適化を実行し、このグラフにマシン・コードを生成できます。

GraalVMには、GraalVMで実行される、プログラミング言語のインタプリタをビルドするためのJavaで記述されたライブラリ(Truffle言語実装フレームワーク)も含まれています。このため、これらの言語は、Graalコンパイラの最適化の可能性のメリットを得ることができます。このようなコンパイルのパイプラインは次のとおりです:

Ahead-of-Timeコンパイル

Truffleフレームワークに加えて、GraalVMでは、その最適化コンパイラが高度なAhead-of-Time (AOT)コンパイル・テクノロジであるネイティブ・イメージに組み込まれています。これは、JavaおよびJVMベースのコードをネイティブ・プラットフォームの実行可能ファイルに変換します。これらのネイティブ実行可能ファイルは、ほぼ瞬時に起動し、より小さく、かつ同じJavaアプリケーションのリソースの消費がより少ないため、クラウド・デプロイメントおよびマイクロサービスに最適です。AOTコンパイルの詳細は、「ネイティブ・イメージ」を参照してください。

コンパイラのオペレーティング・モード

HotSpot JITコンパイラとして使用する場合、Graalコンパイラには、プリコンパイル済マシン・コード(libgraal)または動的に実行されるJavaバイトコード(jargraal)の2つのオペレーティング・モードがあります。

libgraal: Graalコンパイラは、事前にネイティブ共有ライブラリにコンパイルされます。このオペレーティング・モードでは、共有ライブラリはHotSpot VMによってロードされます。コンパイラは、HotSpotヒープとは別のメモリーを使用します。ウォームアップする必要がないため、最初から高速で実行されます。これはデフォルトの推奨操作モードです。

jargraal: Graalコンパイラは、Javaアプリケーションのそれ以外の部分と同じウォームアップ・フェーズを経由します。つまり、ホット・メソッドがコンパイルされる前に最初に解釈されます。このモードは、-XX:-UseJVMCINativeLibraryコマンドライン・オプションを使用して選択します。

診断データ

捕捉されない例外がコンパイラによってスローされた場合、コンパイルは単に破棄され、実行が続行します。Graalコンパイラは、かわりに、バグ・レポートとともに送信できる診断データ(即時表示グラフなど)を生成できます。これは、-Dgraal.CompilationFailureAction=Diagnoseを使用して有効にします。診断出力のデフォルトの場所は、プロセスの現在の作業ディレクトリの下のgraal_dumps/にありますが、-Dgraal.DumpPathオプションを使用して変更できます。VMのシャットダウン中に、診断データを含むアーカイブの場所がコンソールに出力されます。

さらに、-Dgraal.Dumpオプションを使用して、Graalコンパイラによって実行されたコンパイルの診断データを生成できます。これにより、コンパイラによってコンパイルされたすべてのメソッドの診断データが生成されます。診断データが生成される一連のメソッドを絞り込むには、-Dgraal.MethodFilter=<class>.<method>オプションを使用します。たとえば、-Dgraal.MethodFilter=java.lang.String.*,HashMap.getでは、java.lang.Stringクラスのメソッド、および非修飾名がHashMapであるクラスのgetというメソッドの診断データのみが生成されます。

診断データは、ファイルに書き込むかわりに、ネットワークを介してIdeal Graph Visualizerに送信することもできます。これには、-Dgraal.PrintGraph=Networkオプションが必要です。これにより、コンパイラが診断データを127.0.0.1:4445に送信しようとします。このネットワーク・エンドポイントは、-Dgraal.PrintGraphHostおよび-Dgraal.PrintGraphPortオプションを使用して構成できます。

ノート: Ideal Graph Visualizerは、Oracle GraalVM Enterprise Editionで使用できます。