JProfiler ヘルプDownload

CPU プロファイリング


JProfiler がメソッドコールの実行時間をその呼び出しスタックと共に測定する場合、それを「CPU プロファイリング」と呼びます。このデータはさまざまな方法で提示されます。解決しようとしている問題に応じて、どのプレゼンテーションが最も役立つかが決まります。CPU データはデフォルトでは記録されず、興味深いユースケースをキャプチャするには CPU 記録をオンにする 必要があります。

呼び出しツリー

すべてのメソッドコールとその呼び出しスタックを追跡すると、かなりの量のメモリを消費し、すべてのメモリが使い果たされるまで短時間しか維持できません。また、忙しい JVM でのメソッドコールの数を直感的に把握するのは簡単ではありません。通常、その数は非常に多いため、トレースを特定して追跡することは不可能です。

もう一つの側面は、多くのパフォーマンス問題が収集されたデータを集約することで初めて明確になることです。このようにして、特定の時間期間における全体の活動に対するメソッドコールの重要性を判断できます。単一のトレースでは、見ているデータの相対的な重要性を把握することはできません。

これが、JProfiler が観察されたすべての呼び出しスタックの累積ツリーを構築し、観察されたタイミングと呼び出し回数で注釈を付ける理由です。時間的な側面は排除され、合計数のみが保持されます。ツリー内の各ノードは、少なくとも一度は観察された呼び出しスタックを表します。ノードには、その呼び出しスタックで見られたすべての発信コールを表す子がいます。

A B  A B C    A B DA: 7 msB: 6 msC: 3 msD: 1 msA C  2 ms1 ms3 ms1 msC: 1 msメソッド呼び出しと呼び出しスタック呼び出しツリー

呼び出しツリーは「CPU ビュー」セクションの最初のビューであり、CPU プロファイリングを開始する際の良い出発点です。メソッドコールを開始点から最も細かい終点まで追跡するトップダウンビューは最も理解しやすいです。JProfiler は子を合計時間でソートするため、ツリーを深さ優先で開いて、パフォーマンスに最も影響を与える部分を分析できます。

すべての測定はメソッドに対して行われますが、JProfiler はクラスまたはパッケージレベルで呼び出しツリーを集約することで、より広い視点を提供します。集約レベルセレクターには「JEE/Spring コンポーネント」モードも含まれています。アプリケーションが JEE または Spring を使用している場合、このモードを使用してクラスレベルで JEE および Spring コンポーネントのみを表示できます。URL のような分割ノードはすべての集約レベルで保持されます。

呼び出しツリーフィルター

すべてのクラスのメソッドが呼び出しツリーに表示される場合、ツリーは通常管理できないほど深くなります。アプリケーションがフレームワークによって呼び出される場合、呼び出しツリーの上部はフレームワーククラスで構成され、関心がなく、自分のクラスは深く埋もれています。ライブラリへのコールは、その内部構造を示し、数百レベルのメソッドコールが表示される可能性があり、これらを影響を与えることはできません。

この問題の解決策は、呼び出しツリーにフィルターを適用し、一部のクラスのみを記録することです。ポジティブな副作用として、収集するデータが少なくなり、計測するクラスが少なくなるため、オーバーヘッドが削減されます。

デフォルトでは、プロファイリングセッションは一般的に使用されるフレームワークおよびライブラリから除外されたパッケージのリストで構成されています。

もちろん、このリストは不完全なので、削除して自分で関心のあるパッケージを定義する方が良いです。実際、計測とデフォルトフィルターの組み合わせは非常に望ましくないため、JProfiler はセッション開始ダイアログで変更を提案します。

フィルター式は完全修飾クラス名と比較されるため、com.mycorp.com.mycorp.myapp.Application のようなすべてのネストされたパッケージ内のクラスに一致します。フィルターには「プロファイルされた」、「コンパクト」、「無視された」という3つのタイプがあります。「プロファイルされた」クラス内のすべてのメソッドが測定されます。これは自分のコードに必要なものです。

「コンパクト」フィルターに含まれるクラスでは、そのクラスへの最初のコールのみが測定されますが、内部コールは表示されません。「コンパクト」はライブラリ、特に JRE に適しています。たとえば、hashMap.put(a, b) を呼び出すとき、呼び出しツリーに HashMap.put() を表示したいかもしれませんが、それ以上はありません。内部動作は不透明として扱われるべきです。

最後に、「無視された」メソッドはまったくプロファイルされません。オーバーヘッドの考慮から計測が望ましくない場合や、動的コールの間に挿入される内部 Groovy メソッドのように、呼び出しツリーで単に気を散らす場合があります。

パッケージを手動で入力するのはエラーが発生しやすいため、パッケージブラウザを使用できます。セッションを開始する前に、パッケージブラウザは構成されたクラスパス内のパッケージのみを表示できますが、実際にロードされるすべてのクラスをカバーすることはできません。実行時には、パッケージブラウザはすべてのロードされたクラスを表示します。

構成されたフィルターのリストは、各クラスに対して上から下に評価されます。各段階で、一致がある場合、現在のフィルタータイプが変更されることがあります。フィルターリストを開始するフィルターの種類が重要です。「プロファイルされた」フィルターで開始すると、クラスの初期フィルタータイプは「コンパクト」になり、明示的な一致のみがプロファイルされます。

a.*a.b.*a.b.c.*a.Aa.b.Ba.b.c.Cデフォルト:123結果:d.Dプロファイルクラスコンパクトフィルター一致

「コンパクト」フィルターで開始すると、クラスの初期フィルタータイプは「プロファイルされた」になります。この場合、明示的に除外されたクラスを除いて、すべてのクラスがプロファイルされます。

a.*a.b.*a.b.c.*a.Aa.b.Ba.b.c.Cデフォルト:123結果:d.Dプロファイルクラスコンパクトフィルター一致

呼び出しツリーの時間

呼び出しツリーを正しく解釈するには、呼び出しツリーノードに表示される数値を理解することが重要です。任意のノードにとって興味深い時間は2つあります。合計時間と自己時間です。自己時間は、ノードの合計時間からネストされたノードの合計時間を引いたものです。

通常、自己時間は小さいですが、コンパクトフィルターされたクラスではそうではありません。ほとんどの場合、コンパクトフィルターされたクラスはリーフノードであり、合計時間は自己時間と等しくなります。時々、コンパクトフィルターされたクラスがプロファイルされたクラスを呼び出すことがあります。たとえば、コールバックを介して、または呼び出しツリーのエントリーポイントであるためです。この場合、プロファイルされていないメソッドが時間を消費しましたが、呼び出しツリーには表示されません。その時間は呼び出しツリーの最初の利用可能な祖先ノードにバブルアップし、コンパクトフィルターされたクラスの自己時間に寄与します。

A: 自己時間 1 msC: 自己時間 3 msB: 自己時間 2 ms プロファイルクラスコンパクトフィルターB: 自己時間 6 msX: 自己時間 3 msY: 自己時間 1 ms実際の呼び出しシーケンスフィルタリングされた呼び出しシーケンス

呼び出しツリーのパーセンテージバーは合計時間を示しますが、自己時間の部分は異なる色で表示されます。メソッドは、同じレベルで2つのメソッドがオーバーロードされていない限り、シグネチャなしで表示されます。ビュー設定ダイアログで呼び出しツリーノードの表示をカスタマイズするさまざまな方法があります。たとえば、自己時間や平均時間をテキストとして表示したり、メソッドシグネチャを常に表示したり、使用する時間スケールを変更したりできます。また、パーセンテージ計算は、親時間に基づいて行うこともできます。

スレッドステータス

呼び出しツリーの上部には、表示されるプロファイリングデータのタイプと範囲を変更するいくつかのビュー パラメータがあります。デフォルトでは、すべてのスレッドが累積されます。JProfiler はスレッドごとに CPU データを維持し、単一のスレッドまたはスレッドグループを表示できます。

常に、各スレッドには関連付けられたスレッドステータスがあります。スレッドがバイトコード命令を処理する準備ができているか、現在 CPU コアで実行している場合、スレッドステータスは「Runnable」と呼ばれます。このスレッド状態は、パフォーマンスのボトルネックを探す際に興味深いものであるため、デフォルトで選択されています。

代わりに、スレッドがモニターを待機している場合、たとえば Object.wait() または Thread.sleep() を呼び出している場合、スレッド状態は「Waiting」と呼ばれます。synchronized コードブロックの境界でモニターを取得しようとしてブロックされているスレッドは、「Blocking」状態にあります。

最後に、JProfiler はスレッドがネットワークデータを待機している時間を追跡する合成「Net I/O」状態を追加します。これはサーバーやデータベースドライバーを分析する際に重要です。なぜなら、その時間はパフォーマンス分析、たとえば遅い SQL クエリの調査に関連する可能性があるからです。

実時間を知りたい場合は、スレッドステータス「すべての状態」を選択し、単一のスレッドも選択する必要があります。その場合にのみ、コード内で System.currentTimeMillis() を呼び出して計算した時間と比較できます。

選択したメソッドを別のスレッドステータスにシフトしたい場合は、メソッドトリガーと「スレッドステータスを上書きする」トリガーアクションを使用するか、埋め込みまたはインジェクションプローブ API の ThreadStatus クラスを使用して行うことができます。

呼び出しツリーでのノードの検索

呼び出しツリーでテキストを検索する方法は2つあります。まず、ビュー→検索 をメニューから呼び出すか、呼び出しツリーに直接入力を開始することでアクティブになるクイック検索オプションがあります。マッチがハイライトされ、PageDown を押すと検索オプションが利用可能になります。ArrowUp および ArrowDown キーを使用して、異なるマッチを循環できます。

メソッド、クラス、またはパッケージを検索するもう一つの方法は、呼び出しツリーの下部にあるビュー フィルターを使用することです。ここでは、カンマ区切りのフィルター式のリストを入力できます。"-" で始まるフィルター式は無視されたフィルターのようなものです。"!" で始まる式はコンパクトフィルターのようなものです。他のすべての式はプロファイルされたフィルターのようなものです。フィルター設定と同様に、初期フィルタータイプはクラスがデフォルトで含まれるか除外されるかを決定します。

ビュー設定テキストフィールドの左側にあるアイコンをクリックすると、ビュー フィルター オプションが表示されます。デフォルトでは、マッチングモードは「含む」ですが、特定のパッケージを検索する場合、「開始」である方が適切かもしれません。

フレームグラフ

呼び出しツリーをフレームグラフとして表示する別の方法があります。関連する 呼び出しツリー分析 を呼び出すことで、呼び出しツリー全体またはその一部をフレームグラフとして表示できます。

フレームグラフは、呼び出しツリーの全内容を1つの画像で表示します。コールはフレームグラフの下部から始まり、上部に向かって伝播します。各ノードの子は、その直上の行に配置されます。子ノードはアルファベット順にソートされ、親ノードの中心に配置されます。各ノードで費やされた自己時間のために、「炎」は上に向かって徐々に狭くなります。ノードに関する詳細情報は、ツールチップに表示され、テキストをマークしてクリップボードにコピーできます。

マウスカーソルの近くのツールチップが分析を妨げる場合は、右上のボタンでロックし、ツールチップの上部にあるグリッパーで便利な場所に移動できます。同じボタンまたはフレームグラフをダブルクリックすると、ツールチップが閉じます。

フレームグラフは非常に高い情報密度を持っているため、選択したノードとその子孫ノードの階層に焦点を当てることで表示されるコンテンツを絞り込む必要があるかもしれません。興味のある領域をズームインすることもできますが、コンテキストメニューを使用して新しいルートノードを設定することもできます。連続してルートを変更する場合、ルートの履歴で戻ることができます。

フレームグラフを分析する別の方法は、クラス名、パッケージ名、または任意の検索語に基づいてカラー化を追加することです。カラー化はコンテキストメニューから追加でき、カラー化ダイアログで管理できます。各ノードには最初に一致するカラー化が使用されます。カラー化はプロファイリングセッション間で永続化され、すべてのセッションとスナップショットに対してグローバルに使用されます。

カラー化に加えて、クイック検索機能を使用して興味のあるノードを見つけることができます。カーソルキーを使用してマッチ結果を循環し、現在ハイライトされているマッチのツールチップが表示されます。

ホットスポット

アプリケーションが遅すぎる場合、最も時間を要するメソッドを見つけたいと思うでしょう。呼び出しツリーを使用すると、これらのメソッドを直接見つけることができる場合がありますが、多くの場合、呼び出しツリーが広く、リーフノードの数が非常に多いため、うまくいきません。

その場合、呼び出しツリーの逆が必要です。すべてのメソッドをその合計自己時間でソートしたリストで、異なる呼び出しスタックから累積され、メソッドがどのように呼び出されたかを示すバックトレースがあります。ホットスポットツリーでは、リーフはエントリーポイントであり、アプリケーションの main メソッドやスレッドの run メソッドのようなものです。ホットスポットツリーの最も深いノードから、コールはトップレベルノードに向かって上に伝播します。

バックトレースの呼び出し回数と実行時間はメソッドノードを指しているのではなく、このパスに沿ってトップレベルホットスポットノードが呼び出された回数を指しています。これは理解することが重要です。表面的には、ノードの情報がそのノードへの呼び出しを定量化することを期待するかもしれません。しかし、ホットスポットツリーでは、その情報はトップレベルノードへのノードの貢献を示しています。この逆の呼び出しスタックに沿って、トップレベルホットスポットが n 回呼び出され、合計 t 秒の期間がありました。

メソッド Aカウント 5メソッド Cカウント 3メソッド Cカウント 1メソッド Bカウント 2呼び出しツリーホットスポットメソッド Cカウント 4メソッド Aカウント 3メソッド Bカウント 1バックトレースホットスポット呼び出し回数反転

デフォルトでは、ホットスポットは自己時間から計算されます。合計時間から計算することもできます。これはパフォーマンスのボトルネックを分析するのにはあまり役立ちませんが、すべてのメソッドのリストを見たい場合には興味深いかもしれません。ホットスポットビューはオーバーヘッドを減らすために最大数のメソッドのみを表示するため、探しているメソッドが表示されない場合があります。その場合、パッケージまたはクラスをフィルターするために下部のビュー フィルターを使用してください。呼び出しツリーとは異なり、ホットスポットビューのフィルターはトップレベルノードのみをフィルターします。ホットスポットビューのカットオフはグローバルに適用されるのではなく、表示されるクラスに対して適用されるため、フィルターを適用した後に新しいノードが表示されることがあります。

ホットスポットとフィルター

ホットスポットの概念は絶対的なものではなく、呼び出しツリーフィルターに依存します。呼び出しツリーフィルターがまったくない場合、最大のホットスポットはおそらく常に JRE のコアクラスのメソッド、たとえば文字列操作、I/O ルーチン、コレクション操作などになります。このようなホットスポットはあまり役に立ちません。なぜなら、これらのメソッドの呼び出しを直接制御することはほとんどなく、それらを高速化する方法もないからです。

あなたにとって役立つホットスポットは、自分のクラス内のメソッドか、直接呼び出すライブラリクラス内のメソッドである必要があります。呼び出しツリーフィルターの観点から、自分のクラスは「プロファイルされた」フィルターにあり、ライブラリクラスは「コンパクト」フィルターにあります。

パフォーマンスの問題を解決する際には、ライブラリレイヤーを排除し、自分のクラスのみを見たいかもしれません。ホットスポットオプションポップアップで 呼び出しプロファイルされたクラスに追加 ラジオボタンを選択することで、その視点にすばやく切り替えることができます。

呼び出しグラフ

呼び出しツリーとホットスポットビューの両方で、特に再帰的に呼び出される場合、各ノードが複数回出現することがあります。ある状況では、各メソッドが一度だけ出現し、すべての入出力コールが表示されるメソッド中心の統計に興味があるかもしれません。このようなビューはグラフとして表示するのが最適であり、JProfiler ではこれを呼び出しグラフと呼びます。

グラフの欠点の一つは、ツリーよりも視覚的な密度が低いことです。このため、JProfiler はデフォルトでパッケージ名を省略し、合計時間の 1% 未満の発信コールをデフォルトで非表示にします。ノードに発信拡張アイコンがある限り、再度クリックしてすべてのコールを表示できます。ビュー設定では、このしきい値を設定し、パッケージの省略をオフにすることができます。

呼び出しグラフを展開すると、特に複数回バックトラックする場合、非常に混乱する可能性があります。元の状態を復元するには、元に戻す機能を使用してください。呼び出しツリーと同様に、呼び出しグラフもクイック検索を提供します。グラフに入力することで検索を開始できます。

グラフとツリービューにはそれぞれ利点と欠点があるため、ビュータイプを切り替えたい場合があります。インタラクティブセッションでは、呼び出しツリーとホットスポットビューはライブデータを表示し、定期的に更新されます。ただし、呼び出しグラフはリクエストに応じて計算され、ノードを展開しても変更されません。呼び出しツリーの 呼び出しグラフで表示 アクションは、新しい呼び出しグラフを計算し、選択したメソッドを表示します。

グラフから呼び出しツリーに切り替えることはできません。なぜなら、データは通常、後の時点で比較できなくなるからです。ただし、呼び出しグラフは、ビュー→分析 アクションを使用して、選択したノードごとに累積された発信コールとバックトレースのツリーを表示できる呼び出しツリー分析を提供します。

基本を超えて

呼び出しツリー、ホットスポットビュー、呼び出しグラフのセットには、多くの高度な機能があり、別の章で詳細に説明されています。また、別々に紹介される他の高度な CPU ビューもあります。