よくある質問

プロファイリングにユニット・テストを使用できますか。

可能ですが、通常は推奨されません。ユニット・テストを使用してプロファイルを生成するには、任意のアプリケーションのネイティブ実行可能ファイルを生成するのと同じ方法で、テスト・スイート用にインストゥルメントされたバイナリを生成する必要があります。たとえば、テスト・ハーネスを開始するmain()メソッドを設定できます。インストゥルメントされたバイナリが実行されると、インストゥルメントされたバイナリと同様に、プロファイルとともにファイルがダンプされます。

プロファイルに基づく最適化の品質は、最適化されるネイティブ・ビルドへの入力として提供するプロファイルの品質に依存することに注意してください。テストが本番で実行されるワークロードを正確に表していることを確認する必要があります。一般に、次の理由から、それを保証するのは簡単ではありません:

たとえば、静的コンテンツを提供するWebサーバーを実装しているとします。ほとんどの場合、Webサーバーはディスクまたはインメモリー・キャッシュからファイルを読み取り、そのファイルを圧縮して、ネットワーク経由で圧縮バイトを送信します。ただし、適切なユニットテスト・スイートは、構成ファイルの解析、キャッシュの無効化、リモート・デバッグのコードなど、Webサーバーのすべてのコンポーネントをテストします。このコードは、Webサーバーの通常の実行中にほとんど実行されないかまったく実行されない可能性があります。すべてのユニット・テストでプロファイルを収集すると、実際にはほとんど実行されないコードの一部が過剰に反映され、コンパイラの最適化が誤ったものになります。

結論としては、可能ですが、ユニット・テストをプロファイルとして使用することはお薦めしません。これは、ユニット・テストがアプリケーションの処理をどの程度適切に表すかは明確ではないためです。かわりに次のことをお薦めします:

PGOプロファイルは十分にクロス・プラットフォームですか。それとも各ターゲットを個別にインストゥルメントする必要がありますか。

はい。ほとんどの場合、PGOプロファイルは十分にクロスプラットフォームです。あるプラットフォームでインストゥルメントされたバイナリを実行してプロファイルを収集し、そのプロファイルを使用して別のプラットフォームで最適化されたネイティブ実行ファイルをビルドできます。

バイナリがビルドされたプラットフォームによっては、ネイティブ・イメージで異なるクラスおよびメソッドが使用される場合があります。たとえば、PosixProcessPropertiesSupportクラスにはPOSIXベースのシステムでプロセスを操作するコードが含まれ、WindowsProcessPropertiesSupportクラスにはWindowsでプロセスを操作するコードが含まれます。同様に、JDKの一部にはプラットフォーム固有のコードが含まれています。このような場合、プロファイルにはあるプラットフォーム用のエントリが含まれますが、最適化されたネイティブ・ビルドでは、そのプラットフォーム固有のコードのプロファイル・エントリは検出されません。このようなコーナー・ケースはまれであり、通常はパフォーマンスへの影響はありませんが、注意が必要です。

結論として、ベスト・プラクティスは常に、最適化されるネイティブ実行可能ファイルのターゲットと同じプラットフォーム上のプロファイルを収集することです。しかし、異なるプラットフォームで収集したプロファイルを使用しても、通常はうまく機能します。

プロファイリング情報は、コードの変更が限定的なものであれば、変更後再利用できますか。それとも、ビルドごとに新しいプロファイリング情報を収集する必要がありますか。

はい。プロファイリング情報は常に再利用でき、ネイティブ実行可能ファイルが正しく生成されるはずです。ビルドごとに新しいプロファイリング情報を収集する必要はありません。

ただし、最適化されたネイティブ実行可能ファイルのパフォーマンスへの影響は、プロファイルの品質に依存することに注意してください。プログラムの新しいコードが、プロファイルが収集されたコードと大幅に異なる場合、コンパイラの最適化でどのコードが重要なのかが見誤られます。コードの変更が十分に小さいか、プログラムのコールド部分に限定されている場合、古いプロファイルを使用しても最適化されたネイティブ・バイナリのパフォーマンスが低下することは通常ありません。

このトピックの詳細は、「プロファイルの品質の追跡」のガイドラインを参照してください。

インストゥルメントされたバイナリを使用してベンチマークを実行することもできますか。

はい、インストゥルメントされたバイナリは、ベンチマークを含む任意のプログラムに対して生成できます。実際、プロファイルを収集するには、代表的なベンチマークを使用してプロファイルを収集することをお薦めします。

インストゥルメンテーションのオーバーヘッドにより、通常、インストゥルメントされたバイナリはデフォルト(インストゥルメントされていない)ネイティブ実行可能ファイルより遅くなります。インストゥルメンテーションのオーバーヘッドを最小限に抑えるために継続的に努力していますが、インストゥルメントされたバイナリが遅くなり、実行するアプリケーションのコード・パターンによって変わる可能性があります。

また、ベンチマークは、本番環境で予想されるワークロードを表すことが理想的です。ベンチマークのワークロードが本番ワークロードに対応すればするほど、PGOが最適化されたネイティブ・ビルドのパフォーマンスにプラスの影響を与える可能性が高くなります。

結論として、ベンチマークが本番で実行するワークロードを正確に表す場合は、インストゥルメントされたベンチマーク・バイナリのプロファイルを収集し、その後、これらのプロファイルを使用して本番ワークロード用に最適化されたネイティブ実行可能ファイルをビルドすることをお薦めします。

GraalVMは、Webアプリケーションをプロファイリングするためのワークロードをどのように生成しますか。

GraalVM自体は、ネイティブ・イメージでコンパイルされたWebアプリケーションをプロファイリングするためのワークロードを生成しません。かわりに、ロード・テスト・ツールを使用してワークロードを生成する必要があります。

たとえば、Webアプリケーションが複数のHTTPエンドポイントを公開する場合、wrkなどのロード・テスターを使用して、それらのHTTPエンドポイントへのリクエストのストリームを生成する必要があります。この設定は次のようになります。Webアプリケーションのインストゥルメントされたバイナリをビルドし、あるプロセスで起動し、別のプロセスでwrkなどのロード・テスターを起動します。ロードテストの期間は、本番環境で発生すると予想されるリクエスト・ペイロードを使用して、本番ユーザーが最も頻繁にアクセスするWebアプリケーションのエンドポイントを実行するのに十分な長さである必要があります。単純なWebアプリケーションの場合、通常、1分の期間は良質のプロファイルを生成するのに十分です(ただし、これは特定のアプリケーションによって異なります)。ロードテストが完了し、Webアプリケーションが終了すると、プロファイルがファイルにダンプされます。

しばらくの間、本番環境でプロファイルを収集するのはどうですか。たとえば、サービスの1つのインスタンスでのみ月曜日の8:00から12:00まで収集します。

それはプロファイルを収集する良い方法です。

インストゥルメントされたバイナリには、特定のアプリケーションのコード・パターンに依存する特定のオーバーヘッドがあります。ただし、特定の期間にインストゥルメントされたバイナリを1つのインスタンスのみが使用し、サービスの他のすべてのインスタンスが通常またはPGO最適化ビルドを使用する場合、これは実際には一般的に許容されます。

このトピックの詳細は、「プロファイルの品質の追跡」のガイドラインを参照してください。