どう書いてい正しいマイクロベンチマークにJava?
-
20-08-2019 - |
質問
どう書きます(実行)の正しいマイクロベンチマークにJava?
話を楽しめるように設定しましたサンプルコード、コメントを示す様々なことを考えています。
例:のベンチマーク計測時間の繰り返しまたは反復時、なぜですか?
解決
ッションデザイナーやラベル書きマイクロベンチマーク からのクリエイターをJavaのホットスポット:
ルール0: 読みは、信頼できる論文JVMsマイクロベンチマーキング.ができない生活を送っているとは Brian Goetz2005年.いあまり期待していませんでからマイクロベンチマーク;その測定に限られ、JVMの性能特性.
ルール1: 常時出場しているウォームアップ相る試験カーネル全体を通じて、すべてのトリガinitializations、編集前のタイミング位相(s)です。(少なく繰り返しでOKですので、ウォームアップます。の経験則は数万の内側のループ回.)
ルール2: 常に走 -XX:+PrintCompilation
, -verbose:gc
, 等 できることを確認のコンパイラおよびその他の部品のJVMではな予期せぬ作業中のタイミングます。
ルール2.1: 印刷のメッセージの開始と終了のタイミングやウォームアップ段階でできることを確認ありませんからの出力ルール2の間にタイミングます。
ルール3: 意識の違い -client
や -server
, は、OSR、通常の編集.の -XX:+PrintCompilation
フラグを報告OSR編集コミ-サインを主張するためには非初期エントリポイントは、例えば: Trouble$1::run @ 2 (41 bytes)
.好みのサーバクライアントは、定期的にOSR場合には、後で最高の性能を実現できます。
ルール4: この初期化。プリントはありませんの初期のタイミング段階から印刷負荷および初期化します。いないという新しい授業外でのウォームアップ相(又は最終報告相)を除き、試験クラスローディング具体的には(その場合は負荷の試験教室).ルール2における最初の防衛線"。
ルール5: このdeoptimizationと再編簒ます。な任意のコードのパスの初期段階でのコンパイラが迷惑および再コンパイルのコードに基づき、以前の楽観的な想定の軌道に乗せるためには使用しない。ルール2における最初の防衛線"。
ルール6: 適切なツールのコンパイラの心や期待っているさまは、コードを構築しています。検査コードの前の形成について理論的に何が何かりにくくする。
ルール7: ノイズを低減に測定します。お客様のベンチマークがあり、機械とで、廃棄値.使用 -Xbatch
にserializeのコンパイラの応用の検討 -XX:CICompilerCount=1
防止のためのコンパイラの実行と並行します。あなたの最善を尽くし、そして削減にGCオーバーヘッドセット Xmx
(大きく)equals Xms
-利用 UseEpsilonGC
場合であればご利用いただけます。
原則8: 図書館でのごベンチマークとしてでより効率的でしたデバッグがこの唯一の目的です。など JMH, キャリパー または Billトポールに優れに加えて,ucsdのベンチマークのJava.
他のヒント
私はこの表示をして回答ありがたかったのもつライブラリを記マイクロベンチマーク
はじめにチュートリアル
はじめにチュートリアル
これからも私たちは時代の変化とJavaベンチマーク:
- ウォームアップさせ、最大限のJIT初により、コードを実行回数 前のタイミング で
- すでに十分な期間を計測することができる結果を秒以上(い)数十秒
- ができないコ
System.gc()
間で繰り返しなので、アイデアの間で検査で、それぞれの試験今回は"クリーン"モスペースするのに用いられております。("Yes"、gc()
りのヒントよりも保証もの れ でもすごみ収集は私の経験です。) - 私のように表示繰り返し時点の時間繰り返し処理できるスケールの"ベスト"アルゴリズムが得点が1.0、その他ゴールを決める相対的なファッション。このことは走行でき すべての アルゴリズムのためのlongish時間変化とともに、繰り返し、時間も匹敵します。
私のブログのデザインがベンチマーキングの枠組みます。います。がん カップル の 前の投稿 できるので過ごせばよいかを教えてくれるアイデアをすべてまかなえるわけではないのが妥当だろうが、あしたものであってもよい。
jmh 最近のほか、OpenJDKおよび記されている一部の性能技術者からOracle.確かに一見の価値があります。
のjmhはJava ーハーネス用ビル、ランニング、分析ナノ/マイクロ-マクロベンチマークJavaで記述されたその他の言語の入門としてもふさわしく、JVM.
非常に興味深い情報に埋もれて サンプル試験のコメント.
参照:
のベンチマーク計測時間の繰り返しまたは反復時、なぜですか?
もよります 何 しようとしています。
ご興味のある方に 遅延, 使用時間の繰り返し、ご興味のある方に スループット, 使用回/時間。
あなたは何とかベンチマークコードで計算された結果を使用していることを確認してください。そうでなければ、あなたのコードでは、離れて最適化することができます。
あなたは2つのアルゴリズムを比較しようとしている場合は、順序を交互ごとに、少なくとも二つのベンチマークが、やります。すなわち:ます。
for(i=1..n)
alg1();
for(i=1..n)
alg2();
for(i=1..n)
alg2();
for(i=1..n)
alg1();
私は別のパスで同じアルゴリズムの実行時におけるいくつかの顕著な違い(時々、5〜10%)を発見した..
各ループの実行時間が非常に少なくとも10秒程度になるようにまた、必ず N のことを確認することは、非常に大きいです。より多くの反復、あなたのベンチマーク時間でより有効数字やデータであることをより信頼性の高います。
Javaでマイクロベンチマークを書くための多くの可能な落とし穴があります。
まず:ガベージコレクション、キャッシュの効果(ファイル用OSのとメモリのためのCPUの)、IOなど
:あなたは多かれ少なかれランダムな時間がかかる事象のすべての種類を計算する必要があります。第二:あなたは非常に短い間隔で測定された時間の精度を信頼することはできません。
サード:実行中のJVMは、コードを最適化します。だから、同じJVMインスタンス内の別の実行が速くなります。
私の推薦:あなたのベンチマークは、いくつかの秒を走ることには、それはミリ秒を超える実行時よりも信頼性が高いです。 JVM(JVMは、最適化を実行することができ、測定せずに少なくとも一度ベンチマークを実行する手段を)ウォームアップ。そして、あなたのベンチマークを複数回(多分5回)を実行し、中央値をとります。そうでない場合はJVMの最適化の効果は、後でテストを実行している影響を与えることができます(すべてのベンチマーク新しいJavaを呼ぶ)新しいJVMインスタンス内のすべてのマイクロベンチマークを実行します。 (これは、クラスのロードや再コンパイルを引き起こす可能性として)ウォームアップ・フェーズで実行されていないものを、実行しないでください。
また、異なる実装を比較するとき、また、マイクロベンチマークの結果を分析することが重要であるかもしれないことに留意すべきです。したがって有意差検定するがなされるべきである。
実装A
が実装B
よりベンチマークの実行のほとんどの間に速い可能性があるため、このです。しかしA
も高い広がりを持っているかもしれないので、A
の測定された性能上の利点はB
と比較して任意の重要ではありません。
だから、書き、実行するマイクロベンチマークを正しくするだけでなく、それを正しく解析するためにすることも重要である。
http://opt.sourceforge.net/ のJavaのマイクロベンチマーク - 比較を決定するために必要な制御タスク異なるプラットフォーム上のコンピュータシステムの性能特性。最適化の意思決定を導くために、さまざまなJavaの実装を比較するために使用することができます。
他の優れた助言に追加するには、私はまた、次の留意思います:
いくつかのCPU(TurboBoostと例えばインテルCore i5の範囲)、温度(現在使用中のコアの数、ならびにthier利用パーセント)のクロック速度に影響を与えます。 CPUが動的にクロックされているので、これはあなたの結果に影響を与えることができます。あなたはシングルスレッドのアプリケーションを持っている場合たとえば、(TurboBoost付き)最大クロック速度は、すべてのコアを使用したアプリケーションのためのより高いです。したがって、これは、いくつかのシステムでは、単一のマルチスレッド性能の比較を妨害することができます。温度とvolatagesもターボ周波数が維持されているどのくらいの影響を与えることに注意してください。
あなたが正しいことを測定していることを確認してください:あなたが直接制御を持っているおそらく、もっと根本的に重要な側面!たとえば、あなたがベンチマークにコードの特定のビットをSystem.nanoTime()
を使用している場合は、あなたに興味を持っていないものを測定避けるために意味をなす場所での割り当てに電話を入れたとえば、行いません。
long startTime = System.nanoTime();
//code here...
System.out.println("Code took "+(System.nanoTime()-startTime)+"nano seconds");
問題は、あなたがすぐにコードが終了した終了時刻を取得していないです。代わりに、次のことを試してください:
final long endTime, startTime = System.nanoTime();
//code here...
endTime = System.nanoTime();
System.out.println("Code took "+(endTime-startTime)+"nano seconds");