Java で正しいマイクロベンチマークを作成 (および実行) するにはどうすればよいでしょうか?
考慮すべきさまざまな事柄を示すコードサンプルとコメントを探しています。
例: ベンチマークでは時間/反復を測定する必要がありますか、それとも反復/時間を測定する必要がありますか。また、その理由は何ですか。
関連している:ストップウォッチのベンチマークは許容されますか?
ベストアンサー1
マイクロベンチマークを書く際のヒントJava HotSpotの開発者による:
ルール0: JVMとマイクロベンチマークに関する評判の良い論文を読む。良い論文はブライアン・ゲッツ、2005年マイクロベンチマークに過度の期待をしないでください。マイクロベンチマークでは、JVM パフォーマンス特性の限られた範囲しか測定されません。
ルール 1:常にウォームアップ フェーズを含めて、テスト カーネルを最後まで実行し、タイミング フェーズの前にすべての初期化とコンパイルをトリガーできるようにします。(ウォームアップ フェーズでは、反復回数が少なくても問題ありません。経験則では、内部ループの反復回数は数万回です。)
ルール 2:常に-XX:+PrintCompilation
、、-verbose:gc
などを使用して実行し、タイミング フェーズ中にコンパイラや JVM の他の部分が予期しない作業を行っていないことを確認します。
ルール 2.1:タイミング フェーズとウォームアップ フェーズの開始時と終了時にメッセージを出力し、タイミング フェーズ中にルール 2 からの出力がないことを確認します。
ルール 3:-client
と、OSR と通常のコンパイルの違いに注意してください-server
。-XX:+PrintCompilation
フラグは、非初期エントリ ポイントを示すアット マークを付けて OSR コンパイルを報告します (例: ) Trouble$1::run @ 2 (41 bytes)
。最高のパフォーマンスを求める場合は、クライアントよりもサーバーを、OSR よりも通常のコンパイルを優先してください。
ルール 4:初期化の影響に注意してください。印刷はクラスのロードと初期化を行うため、タイミング フェーズ中に初めて印刷しないでください。クラスのロードを具体的にテストしている場合を除き (その場合はテスト クラスのみをロードします)、ウォームアップ フェーズ (または最終レポート フェーズ) 以外で新しいクラスをロードしないでください。ルール 2 は、このような影響に対する最初の防御線です。
ルール 5:最適化解除と再コンパイルの影響に注意してください。タイミング フェーズで初めてコード パスを使用しないでください。これは、パスがまったく使用されないという以前の楽観的な想定に基づいて、コンパイラがコードを破棄して再コンパイルする可能性があるためです。ルール 2 は、このような影響に対する最初の防御線です。
ルール 6:適切なツールを使用してコンパイラの考えを読み、コンパイラが生成するコードに驚かされることを期待してください。何が何かを速くしたり遅くしたりするかについて理論を立てる前に、自分でコードを検査してください。
ルール7:測定のノイズを減らす。静かなマシンでベンチマークを実行し、外れ値を破棄しながら数回実行します。-Xbatch
コンパイラをアプリケーションとシリアル化するために を使用し、コンパイラが並列実行されないように設定することを検討します。GCオーバーヘッドを減らすために最善を尽くし、 (十分に大きい)等号-XX:CICompilerCount=1
を設定し、Xmx
Xms
UseEpsilonGC
利用可能であれば。
ルール8:ベンチマークには、おそらくより効率的で、この目的のためにすでにデバッグされているライブラリを使用します。たとえば、JMH、キャリパーまたはBill と Paul による Java 用の優れた UCSD ベンチマーク。