プロファイルの品質の追跡

ネイティブ・イメージにPGOを使用する場合の最も困難なステップは、関連するワークロードのプロファイルを収集することです。ソース・コードは進化するため、時間が経ってもアプリケーションが変化しないということはほとんどありません。ソース・コードを変更するたびに、「build-instrumented-image」、「gather-profile」および「build-optimized-image」のステップを実行するのに時間がかかる場合があります。このドキュメントでは、アプリケーションのソース・コードが時間の経過とともに変化したときに、既存のプロファイルを引き続き使用できるかという質問に対する回答をいくつか示します。

アプローチ1: プロファイルを無期限に再利用

最適化されたアプリケーションをビルドする場合、ネイティブ・イメージは、指定されたプロファイルで可能なかぎり最善を尽くそうとします。つまり、アプリケーションの古いプロファイル(またはまったく異なるアプリケーションのプロファイル)を提供しても、ネイティブ・イメージがネイティブの実行ファイルを生成するのを止めることはありません。

ノート: プロファイルが正しくないと、プロファイルがないよりもパフォーマンスが低下する可能性があります。これは、プロファイルが正しくないと、コンパイラがアプリケーションの誤った要素に最適化リソースを費やし、重要な要素の優先順位を落とす可能性があるためです。

つまり、進化するアプリケーションに対して1つのプロファイルを無期限に再利用すると、遅かれ早かれ逆効果になります。

アプローチ2: プロファイルを定期的に収集

アプリケーションは定期的に変更される可能性があるため、新しいプロファイルを定期的に収集することが論理的です。これを実現する1つの方法は、マスター・ブランチの先頭を使用してインストゥルメントされたバージョンのアプリケーションをビルドし、ワークロードを実行してプロファイルを収集し、他の最適化ビルドがダウンロードできるFTPサーバーに結果として得られたiprofファイルをアップロードするLinuxのcronジョブを毎日実行することです。これにより、ビルド中のアプリケーション・バージョンと使用中のプロファイルとの差異が、一定の時間間隔(この例では24時間)より大きくなることはありません。

ただし、プロファイルを定期的に収集すると計算時間が長くなるため、アプリケーションの変更頻度とバランスを取る必要があります。アプリケーションが比較的安定していて、ソース・コードが頻繁に変更されない場合、再プロファイル頻度を少なくすることは問題ありません。次のいくつかのことに注意してください:

そうすれば、ワークロードで後で本番環境で実行されるアプリケーションの同じ部分を実行するかぎり、プロファイルが古くなったり、合わなくなったりするリスクはありません。

アプローチ3: プロファイルの品質メトリックの経時的な追跡

プロファイルの品質をよりよく理解するために、ネイティブ・イメージには、最適化された実行可能ファイルをビルドする際にリクエストできる2つのメトリック(プロファイル関連性プロファイル適用性)が用意されています。これらのメトリックは、プロファイルと、最適化された実行可能ファイルに含まれるメソッドとクラスの関係を反映します。

(同じプロファイルを使用する)ビルド間でこれらの2つのメトリックの値が変化している場合は、それらのビルド内のクラスまたはメソッド(あるいはその両方)のセットも(プロファイルが収集された時点から現在のビルドまでの間に)変化していることを示します。

プロファイル品質メトリックを取得する方法

プロファイル品質メトリックを計算して出力するには、最適化されたネイティブ実行可能ファイルをビルドするときに-H:+PGOPrintProfileQualityオプションを渡します。(このオプションは試験的なものです。)

「プロファイルに基づく最適化の基本的な使用法」で紹介したGame of Lifeサンプル・アプリケーションを考えてみます:

native-image -cp . GameOfLife -o gameoflife-pgo --pgo=gameoflife.iprof -H:+PGOPrintProfileQuality

ビルド出力のフェーズ5で、プロファイルの適用性とプロファイルの関連性に関する追加の行が表示されます:

GraalVM Native Image: Generating 'gameoflife-pgo' (executable)
...
[5/8] Inlining methods...     [***]                                                                      (0.4s @ 0.28GB)
Info: PGO: Profile applicability is 21.74%. Profile relevance is 72.71%.
...

これらのメトリックの絶対値からは多くのことは分からないため、単独では考慮しないでください。前述したように、これらのメトリックは、プロファイルとアプリケーションのコード間の関係を示します。アプリケーションを変更してプロファイルを再利用すると、メトリックの値が変化するはずです。

たとえば、applyRules ()アプリケーション・メソッドに単純な"method-rename"リファクタリングを適用します。プロファイルの観点からは、applyRules ()メソッドがアプリケーションのメソッド・セットから削除され、applyGameRulesという新しいメソッドが導入されました。同じプロファイルで最適化されたビルドを再実行すると、変更されたアプリケーションは次の出力を返します:

native-image -cp . GameOfLife -o gameoflife-pgo --pgo=gameoflife.iprof -H:+PGOPrintProfileQuality
========================================================================================================================
GraalVM Native Image: Generating 'gameoflife-pgo' (executable)...
...
[5/8] Inlining methods...     [***]                                                                      (0.4s @ 0.28GB)
Info: PGO: Profile applicability is 21.67%. Profile relevance is 72.66%.                                                                  (6.8s @ 0.29GB)
...

最初のビルドでのプロファイルの適用性は21.74%で、現在は21.67%です。同様に、最初のビルドでのプロファイルの関連性は72.71%で、現在は72.66%です。コードがわずかに変更されると、メトリック値がわずかに変化し、プロファイルが少し古くなっている可能性があることが通知されます。

ノート: この例では、非常にホットなメソッドの名前を変更しました。プロファイルをホット・メソッドに適用できないため、この変更によってパフォーマンスが低下する可能性があります。アプリケーションのコールド・コードで同様の変更を行うと、これらのメトリックも同様に減少しますが、パフォーマンスには影響しません。これらのメトリックは、提供されたプロファイルとアプリケーション内のメソッド・セット間の関係を測定するもので、プロファイル、アプリケーション・ソース・コードまたは依存関係の変更によるパフォーマンスの影響を測定または予測するものではないことに注意してください。また、これらの数値は、1つのビルドで確認した場合、ほとんど意味がないか、ほとんど有用ではありません。この有用性は、ビルド間でプロファイルを再利用したり、アプリケーションの同じビルドに別のプロファイルを提供したりするときに、メトリックの変更を監視することから得られます。

プロファイル品質メトリック: 適用性

適用性メトリックは、このプロファイルはアプリケーションのメソッドにどの程度適用可能かという質問に答えるものです。アプリケーション内の個々のメソッドのコンパイル中に、プロファイルが必要なコード内の場所Nの数、およびプロファイルが使用可能になった回数Sを追跡します。プロファイルの適用性のメトリックは、パーセンテージで表されるS/Nの比率です。

つまり、(プロファイルではなく)アプリケーションに新しいコードを追加すると、プロファイルの適用性が低下します。これは、コードが増えるとプロファイルのリクエストも多くなり、プロファイルを適用できる回数(S)が同じでも、より大きなプロファイルの総リクエスト数(N)で除算されるためです。

ノート: プロファイルの適用性が100%であると期待するのは間違いです。優れたワークロードは、ほとんどの場合、アプリケーションのホット部分とコールド部分を区別し、コードの一部のコールド部分を実行しません。このため、プロファイルには、実際のワークロードではほとんど実行されないアプリケーションのコールド部分(例外ハンドラなど)のエントリは含まれません。100%の適用性は、イメージ内のコードのすべての部分が完全にプロファイルされたことを意味し、実際にはそのようなことはほとんどありません。

プロファイル品質メトリック: 関連性

関連性メトリックは、プロファイルの内容がアプリケーション・メソッドとどの程度一致するかという質問に回答することを目的としています。プロファイルをロードすると、そのすべてのデータが一連のアプリケーション・メソッドと照合され、それらのメソッドに一致しないすべてのエントリが削除されます。たとえば、クラスからメソッドを削除しても、そのメソッドのエントリがまだあるプロファイルを使用する場合、それらのエントリはすべてプロファイル・ロード時に削除されます。プロファイルの関連性は、ロード中に削除されていないデータの割合です。

つまり、(プロファイルからではなく)アプリケーションからコードを削除すると、新しいアプリケーション・バージョンに関連するプロファイル内のデータの割合が減少するため、プロファイルの関連性が低下します。一方、新しいコード(新しいクラスや依存関係など)をアプリケーションに追加しても、プロファイルから削除する必要があるデータの量は変わらないため、このメトリックには影響しません。

ノート: プロファイルの収集に使用したものとまったく同じアプリケーションの最適化バイナリをビルドすれば、プロファイルの関連性が100%になると期待するのは間違いです。インストゥルメントされたバイナリと最適化されたバイナリのメソッドは微妙に異なるため、これは当てはまりません。たとえば、インストゥルメントされたバイナリには、プロファイル・データを収集するためのコードと、そのデータをファイルにシリアライズするためのコードが含まれます。このコードは不要であるため、最適化されたバイナリには存在しません。Game Of Lifeの例を見ると、70%前後の関連性は、主にアプリケーションが非常に小さい(120行未満のJavaクラス1つ)ことに起因しています。したがって、インストゥルメントされたバイナリと最適化されたバイナリのメソッド・セットの違いはかなり誇張されます。より大規模な実際のアプリケーションでは、通常このパーセンテージはより大きくなりますが、100%ではありません。

その他の情報