非同期およびリモートリクエストトラッキング
タスクの非同期実行は、プレーンなJavaコードでも、さらにリアクティブフレームワークでも一般的な手法です。ソースファイルで隣接しているコードが、今や2つ以上の異なるスレッドで実行されます。デバッグとプロファイリングにおいて、これらのスレッド変更は2つの問題を引き起こします。一方では、呼び出された操作がどれほど高価であるかが不明です。他方では、高価な操作を引き起こしたコードに遡ることができません。
JProfilerは、この問題に対して、呼び出しが同じJVM内で行われるかどうかに応じて異なる解決策を提供します。非同期実行がそれを呼び出す同じJVM内で行われる場合、「インライン非同期実行」 呼び出しツリー分析は、呼び出し元サイトと実行サイトの両方を含む単一の呼び出しツリーを計算します。リモートJVMへのリクエストが行われた場合、呼び出しツリーには呼び出し元サイトと実行サイトへのハイパーリンクが含まれており、関係するJVMのプロファイリングセッションを表示する異なるJProfilerのトップレベルウィンドウ間をシームレスにナビゲートできます。
非同期およびリモートリクエストトラッキングの有効化
非同期メカニズムはさまざまな方法で実装でき、別のスレッドまたは異なるJVMでタスクを開始するセマンティクスは一般的な方法では検出できません。JProfilerは、いくつかの一般的な非同期およびリモートリクエスト技術を明示的にサポートしています。リクエストトラッキング設定でそれらを有効または無効にすることができます。デフォルトでは、リクエストトラッキングは有効になっていません。また、セッションが開始される直前に表示されるセッション開始ダイアログでリクエストトラッキングを設定することも可能です。
JProfilerのメインウィンドウでは、ステータスバーがいくつかの非同期およびリモートリクエストトラッキングタイプが有効になっているかどうかを示し、設定ダイアログへのショートカットを提供します。
JProfilerは、プロファイルされたJVMで有効化されていない非同期リクエストトラッキングタイプが使用されている場合、
非同期トラッキング
少なくとも1つの非同期トラッキングタイプが有効化されている場合、CPU、割り当て、プローブ記録の呼び出しツリーおよびホットスポットビューは、すべての有効化されたトラッキングタイプに関する情報を表示し、「インライン非同期実行」呼び出しツリー分析を計算するボタンを提供します。その分析の結果ビューでは、すべての非同期実行の呼び出しツリーが、
別のスレッドでタスクをオフロードする最も簡単な方法は、新しいスレッドを開始することです。JProfilerを使用すると、「スレッド開始」リクエストトラッキングタイプを有効化することで、スレッドの作成から実行サイトまでを追跡できます。ただし、スレッドは重量級オブジェクトであり、通常は繰り返し呼び出しのために再利用されるため、このリクエストトラッキングタイプはデバッグ目的でより有用です。
他のスレッドでタスクを開始する最も重要で一般的な方法は、java.util.concurrent
パッケージのエグゼキュータを使用することです。エグゼキュータは、非同期実行を扱う多くの高レベルのサードパーティライブラリの基盤でもあります。エグゼキュータをサポートすることで、JProfilerはマルチスレッドおよび並列プログラミングを扱うライブラリ全体をサポートします。
上記の一般的なケースに加えて、JProfilerはJVM用の2つのGUIツールキット、AWTとSWTもサポートしています。どちらのツールキットもシングルスレッドであり、GUIウィジェットを操作し描画操作を行うことができる特別なイベントディスパッチスレッドがあります。GUIをブロックしないようにするために、長時間実行されるタスクはバックグラウンドスレッドで実行する必要があります。ただし、バックグラウンドスレッドは進行状況や完了を示すためにGUIを更新する必要があることが多いです。これは、イベントディスパッチスレッドで実行されるようにRunnable
をスケジュールする特別なメソッドで行われます。
GUIプログラミングでは、原因と結果を結びつけるために複数のスレッド変更を追跡する必要があることがよくあります。ユーザーがイベントディスパッチスレッドでアクションを開始し、それがエグゼキュータを介してバックグラウンド操作を開始します。完了後、そのエグゼキュータはイベントディスパッチスレッドに操作をプッシュします。最後の操作がパフォーマンスの問題を引き起こす場合、それは元のイベントから2つのスレッド変更が離れています。
最後に、JProfilerはKotlinコルーチンもサポートしています。Kotlinのマルチスレッドソリューションは、すべてのKotlinバックエンドで実装されています。非同期実行自体はコルーチンが起動されるポイントです。Kotlinコルーチンのディスパッチメカニズムは柔軟で、実際には現在のスレッドで開始することも含まれます。この場合、「非同期実行」ノードにはインライン部分があり、そのノードのテキストで別途報告されます。
サスペンドメソッドは実行を中断し、その後異なるスレッドで再開される可能性があります。サスペンドが検出されたメソッドには、追加の
プロファイルされていない呼び出し元サイトのトラッキング
デフォルトでは、エグゼキュータとKotlinコルーチントラッキングの両方が、呼び出し元サイトがプロファイルされたクラスにある非同期実行のみをトラッキングします。これは、フレームワークやライブラリがこれらの非同期メカニズムをあなた自身のコードの実行に直接関連しない方法で使用する可能性があり、追加された呼び出し元および実行サイトがオーバーヘッドと混乱を引き起こすだけだからです。ただし、プロファイルされていない呼び出し元サイトをトラッキングするユースケースもあります。たとえば、フレームワークがKotlinコルーチンを開始し、その上であなた自身のコードが実行される場合です。
プロファイルされていないクラスでそのような呼び出し元サイトが検出された場合、呼び出しツリーおよびホットスポットビューのトラッキング情報には対応する通知メッセージが表示されます。ライブセッションでは、これらのビューから直接エグゼキュータおよびKotlinコルーチントラッキングのプロファイルされていない呼び出し元サイトのトラッキングを個別にオンにすることができます。これらのオプションは、セッション設定ダイアログの「CPUプロファイリング」ステップでいつでも変更できます。
Kotlinコルーチンは、CPU記録がアクティブな間に起動された場合にのみトラッキングできることを理解することが重要です。後でCPU記録を開始した場合、Kotlinコルーチンからの非同期実行はインライン化できません。JProfilerは、プロファイルされていないクラスでの呼び出し元サイトの検出と同様に通知します。アプリケーションの開始時に開始される長寿命のコルーチンをプロファイルする必要がある場合、アタッチモードを使用することはできません。その場合、-agentpath VMパラメータでJVMを起動し、起動時にCPU記録を開始します。
リモートリクエストトラッキング
選択された通信プロトコルに対して、JProfilerはメタデータを挿入し、JVMの境界を越えてリクエストをトラッキングすることができます。サポートされている技術は次のとおりです:
- HTTP: クライアント側ではHttpURLConnection、java.net.http.HttpClient、Apache Http Client 4.x、Apache Async Http Client 4.x、OkHttp 3.9+、サーバー側では任意のServlet-API実装またはServletなしのJetty
- Jersey Async Client 2.x、RestEasy Async Client 3.x、Cxf Async Client 3.1.1+の非同期JAX-RS呼び出しの追加サポート
- Webサービス: JAX-WS-RI、Apache Axis2、Apache CXF
- RMI
- gRPC
- リモートEJB呼び出し: JBoss 7.1+およびWeblogic 11+
JProfilerでリクエストを追跡するためには、両方のVMをプロファイルし、別々のJProfilerトップレベルウィンドウで同時に開く必要があります。これは、ライブセッションでもスナップショットでも機能します。ターゲットJVMが現在開かれていない場合、またはリモート呼び出しの時点でCPU記録がアクティブでなかった場合、呼び出し元サイトのハイパーリンクをクリックするとエラーメッセージが表示されます。
リモートリクエストをトラッキングする際、JProfilerは関与するJVMの呼び出しツリーで呼び出し元サイトと実行サイトを明示的に示します。JProfilerの呼び出し元サイトは、記録されたリモートリクエストが実行される前の最後のプロファイルされたメソッド呼び出しです。それは、異なるVMに位置する実行サイトでタスクを開始します。JProfilerでは、呼び出しツリービューに表示されるハイパーリンクを使用して、呼び出し元サイトと実行サイトの間をジャンプすることができます。
呼び出し元サイトは、すべてのスレッドに対してリモートリクエストトラッキングに関して同じアイデンティティを持っています。これは、呼び出し元サイトから実行サイトへ、またはその逆にジャンプする際に、スレッド解決がなく、ジャンプは常に「すべてのスレッドグループ」および「すべてのスレッド状態」スレッドステータス選択をアクティブにすることを意味し、ターゲットが表示されるツリーの一部であることが保証されます。
呼び出し元サイトと実行サイトは1:nの関係にあります。呼び出し元サイトは、特に異なるリモートVMにある場合、複数の実行サイトでリモートタスクを開始することができます。同じVM内では、単一の呼び出し元サイトに対して複数の実行サイトがあることはあまり一般的ではありません。なぜなら、それらは異なる呼び出しスタックで発生する必要があるからです。呼び出し元サイトが複数の実行サイトを呼び出す場合、ダイアログでそれらの1つを選択できます。
実行サイトは、特定の呼び出し元サイトによって開始されたすべての実行を含む呼び出しツリー内の合成ノードです。実行サイトノードのハイパーリンクは、その呼び出し元サイトに戻ります。
同じ呼び出し元サイトが同じ実行サイトを繰り返し呼び出す場合、実行サイトはすべての呼び出しのマージされた呼び出しツリーを表示します。それが望ましくない場合は、例外的メソッド機能を使用して、以下のスクリーンショットに示すように呼び出しツリーをさらに分割できます。
実行サイトは単一の呼び出し元サイトからのみ参照されるのに対し、呼び出し元サイト自体は複数の実行サイトにリンクすることができます。呼び出し元サイトの数値IDを使用して、異なる実行サイトから参照されている場合でも同じ呼び出し元サイトを認識できます。さらに、呼び出し元サイトはリモートVMのIDを表示します。プロファイルされたVMのIDはステータスバーに表示されます。それはJProfilerが内部で管理するユニークIDではなく、JProfilerで開かれた新しいプロファイルされたVMごとに1から始まりインクリメントされる表示IDです。