web-dev-qa-db-ja.com

コードセグメントのJava実行時間、メモリ使用量、CPU負荷)の測定

Javaコードの特定のセグメントについて、測定したい:

  • 実行時間(おそらくスレッド実行時間
  • メモリ使用量
  • CPU負荷(特にコードセグメントに起因)

私は親戚ですJava初心者で、これがどのように達成されるかについてはよく知りません。私は [〜#〜] jmx [〜#〜] =ただし、それがどのように使用されるかはわかりません。JMXは、私が探していることに対して少し「重い」ように見えます。

理想的には、コードセグメントの前にstart()メソッドを呼び出し、後にstop()メソッドを呼び出すオプションを使用して、何を測定したいかを伝えることができる測定クラスが必要です。関連するメトリックは、指定したファイルに記録されます。

例えば:

import com.example.metricLogger;

metricLogger logger = new metricLogger();

logger.setLogPath(pathToLogFile);
logger.monitor(executionTime);
logger.monitor(memoryUsage);
logger.monitor(cpuLoad);

logger.start();

/* Code to be measured */

logger.stop();

Javaでこれを達成するための標準/共通/従来の方法はありますか?

このような測定は1回限りのパフォーマンス比較のためのものであるため、本番環境での長期的な監視プロセスは探していません。

チュートリアルや外部の例を参照できてうれしいです。ここで完全な答えを期待することはできません。とは言うものの、上記のような単純なものが達成できれば、現実的な例は本当にうまくいくでしょう。

25
Jon Cram

本番環境の統計は必要ないため、プロファイリングの方が簡単なオプションです。プロファイリングもコードの変更を必要としません。 VisualVM(JDK 1.6.06以降に同梱)はシンプルなツールです。より詳細な情報が必要な場合は、Eclipse TPTP、Netbeansプロファイラー、またはJProfiler(pay)を使用します。

自分で書きたい場合は、次のことを考慮してください。

実行時間などの簡単な測定は、関心のあるセクションを「クロッキング」することで実行できます。

long start = System.nanoTime(); // requires Java 1.5
// Segment to monitor
double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;

同様の手法を使用して、Runtime.getRuntime()。* memory()メソッドを介してメモリを監視できます。ガベージコレクション環境でのメモリ使用量の追跡は、単純な減算よりも注意が必要です。

JavaではCPU負荷を測定するのは難しいので、私は通常、実行時間に固執し、より長い/反復的なセクションを最適化します

19
basszero

ThreadMXBeanを使用すると、個々のスレッドのCPU使用率と、経過時間ではなく消費されたCPU時間を取得できます。これは便利な場合があります。

ただし、このプロセスでは大量のデータが生成されることが多く、何が起こっているかを確認するには優れた視覚化ツールが必要になるため、プロファイラーを使用する方が簡単な場合がよくあります。

私が使用した他のプロファイラーの問題を解決する方が簡単だと思うので、Yourkitを使用します。また、組み込みのhprofを使用します。これにより、アプリケーションのプロファイルについて異なるビューが得られる可能性があります(ただし、それほど有用ではありません)。

5
Peter Lawrey

Java Profilerを使用するのが最良のオプションであり、コードに必要なすべての洞察が得られます。つまり、応答時間、スレッドCallTraces、メモリ使用率など

私はあなたに提案します [〜#〜] jensor [〜#〜] 、オープンソースJavaプロファイラー。使いやすさとCPUのオーバーヘッドが少ないため、ダウンロードしてコードをインストルメント化すると、コードについて必要なすべての情報を取得できます。

次の場所からダウンロードできます: http://jensor.sourceforge.net /

1
M.N

実行中にcpuとメモリのメトリックを収集することで、特定の呼び出されたメソッド中に使用されたcpuとメモリを測定できます。
もちろん、他のメソッドの他の並行スレッドが実行中にメモリとCPUを消費すると、スタックします。したがって、メソッドを分離して実行できる場合は、これは有効なアプローチです。

CPUの場合、現在の値を取得できます。

OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
            OperatingSystemMXBean.class); 
double processCpuLoad = osBean.getProcessCpuLoad();

記憶のためにあなたはそれをすることができます:

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
int currentHeapUsedInMo = (int) (memoryMXBean.getHeapMemoryUsage().getUsed() / 1_000_000);

メモリ対策については、メジャーコレクトを待ってからメソッドを実行することで信頼性が向上します。

たとえば、そのようなものが役立つかもしれません:

import com.google.common.testing.GcFinalization;

GcFinalization.awaitFullGc();
foo.execute(); // method to execute

GcFinalizationGuavaテストライブラリ から取得されます。

オーバーヘッドがほとんどありません。したがって、アイデアは、監視する呼び出されたメソッドごとにメトリック(たとえば、毎秒)を収集し、メソッドが戻ったときに、それらの最大/平均または有用な情報を計算することです。

私はそれをするためにAOPを支持します。
Spring AOPは、アスペクトを作成してポイントカットを設定するためのシンプルで優れた方法ですが、AOP機能に関して特定のことが必要な場合は、AspectJを使用して行うこともできます。

0
davidxxx