私はこの小さな(そして残酷に非効率的な)クラスを作成し、JavaVisualVMを使用してそれをプロファイリングしたいと思いました。
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
int n = Integer.parseInt(args[0]);
int fib = fib(n);
System.out.println(fib);
}
private static int fib(int n) {
if (n < 2) {
return n;
}
return fib(n-1)+fib(n-2);
}
}
結果は奇妙です。結果は、ConnectionHandler.run()の呼び出しによって完全に支配されます。
(98.2%)sun.rmi.transport.tcp.TCPTransport $ ConnectionHandler.run()
(1.7%)java.lang.Thread.join(long)
(0%)java.lang.String.equals(Object)
など。 。
プロファイルされたメソッドはおそらく約100あり、そのうちの1つはfib(int)ではありません。
私のプログラムが実際にすべての時間をこれらの方法に費やしているとは考えられません。それらは私のjvmに接続し、そのことを実行しているプロファイラーのようです。
私は何が間違っているのですか?
わかりやすくするために編集: nに45を渡すと、このアプリケーションは20秒間実行されます。私が最初にプロファイリングしていたプログラム(フィボナッチ計算機ではない)は、CPUの4つのコアすべてを100%でペグし、最大5分間のプロファイリング実行を実行していました。これらは同じ結果であり、私のアプリケーションのメソッドはホットスポットメソッドリストの上位に表示されませんでした。
実行ごとに異なりますが、ConnectionHandler.run()が常に最上位にあり、通常、プロファイル時間の約99%を占めます。
2番目の編集:サンプラーを使用してみましたが、JProfilerが生成しているものと一致する結果が得られています。これの欠点は、プロファイリングに付属するスタックトレース情報を取得できないことです。しかし、私の差し迫ったニーズにとって、これは素晴らしいことです。
遊んでいるときに私が発見したことは、VisualVMがメソッド呼び出しの実時間をプロファイリング中にカウントすることです。
私の特定のケースでは、私のアプリケーションには、ワーカースレッドを起動し、キューでのメッセージの待機をすぐにブロックするメインスレッドがあります。
これは、私のCPUを消費しているのはこのメソッドではないという事実にもかかわらず、ブロッキングメソッドがプロファイラーでほとんどすべての時間を費やしているように見えることを意味します。
同じことがsun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run()メソッドにも当てはまると思いますが、このメソッドは正常に機能しますが、終了すると、アプリケーションで最も長く実行されるメソッドの1つになります。