Graalコンパイラ
Graalコンパイラは動的なコンパイラで、Javaで記述され、バイトコードをマシン・コードに変換します。Graal Just-in-Time (JIT)コンパイラは、Java HotSpot仮想マシンおよびGraalVMと統合されています。詳細は、『Java仮想マシン・ガイド』および「仮想マシンとしてのGraalVM」を参照してください。(Graal JITコンパイラのオープン・ソース・コードは、GitHubで入手できます。)
コンパイラの利点
Graal JITコンパイラは、コード分析および最適化に対する独自のアプローチによって、Java仮想マシン(JVM)で実行されているアプリケーションのパフォーマンスを最適化します。これには、積極的なインライン化、多相インライン化など、複数の最適化アルゴリズム(フェーズと呼ばれる)が含まれています。
Graalコンパイラは、高度に抽象化されたプログラムのパフォーマンスの利点をもたらすことができます。たとえば、特定のオブジェクトのコストのかかる割当てを削除できる部分エスケープ分析の最適化が含まれています。詳細は、GraalVM GitHubリポジトリのCEOptimization enum
の値PartialEscapeAnalysis
を参照してください。この最適化は、新しいオブジェクトがコンパイル単位の外部からアクセス可能になるタイミングを決定し、コンパイル単位を「エスケープ」するパス(オブジェクトがパラメータとして渡されるか、フィールドに格納されるか、メソッドから戻されるなど)でのみ割当てを行います。このアプローチにより、ヒープ割当ての数を削減することで、アプリケーションのパフォーマンスを大幅に向上できます。StreamやLambdaなど、より最新のJava機能を使用するコードでは、パフォーマンスが大幅に向上します。この種のコードには、非エスケープまたは部分エスケープ・オブジェクトが多数含まれるためです。I/Oやメモリー割当てなど、コンパイラで削除できない特性にバインドされているコードは、あまり改善されません。パフォーマンス・チューニングの詳細は、「Graal JITコンパイラ構成」を参照してください。
グラフ・コンパイル
ゲスト・プログラミング言語(つまりJavaScript、PythonおよびRuby)をホストJVMベース言語と同じランタイムで実行するため、コンパイラは、ソース言語と生成されるマシン・コードの間で言語に依存しない中間グラフ表現を使用します。(言語の相互運用性の詳細は、「相互運用性」を参照してください。)
グラフは、if文やループなど、異なる言語の類似した文を同じ方法で表すことができるため、同じアプリケーション内で言語を混在させることができます。これにより、Graalコンパイラは、言語に依存しない最適化を実行し、このグラフにマシン・コードを生成できます。
診断データ
捕捉されない例外がコンパイラによってスローされた場合、通常、コンパイルは破棄され、実行が続行します。Graalコンパイラは、かわりに、バグ・レポートとともに送信できる診断データ(即時表示グラフなど)を生成できます。これは、-Djdk.graal.CompilationFailureAction=Diagnose
オプションを使用して有効にします。診断出力のデフォルトの場所は、プロセスの現在の作業ディレクトリの下のgraal_dumps/ディレクトリにありますが、-Djdk.graal.DumpPath
オプションを使用して変更できます。JVMのシャットダウン中に、診断データを含むアーカイブの場所がコンソールに出力されます。
さらに、-Djdk.graal.Dump
オプションを使用して、Graalコンパイラによって実行されたコンパイルの診断データを生成できます。これにより、コンパイラによってコンパイルされたすべてのメソッドの診断データが生成されます。
診断データが生成される一連のメソッドを絞り込むには、-Djdk.graal.MethodFilter=<class>.<method>
オプションを使用します。たとえば、-Djdk.graal.MethodFilter=java.lang.String.*,HashMap.get
では、java.lang.String
クラスのメソッド、および非修飾名がHashMap
であるクラスのget
というメソッドの診断データのみが生成されます。