Application Real-Time Monitoring Service (ARMS) のコード診断機能は、継続的プロファイリング技術を使用して、スレッドのメソッドスタックスナップショットを定期的に収集し、コード実行をシミュレートします。
シナリオ
プロモーションでスローコールが発生した場合、コード診断機能は問題のあるコードを迅速に特定できます。
システムで多数のスローコールが発生した場合、この機能は問題のあるコードを自動的に保存できます。
ビジネスが複雑すぎて、散発的なスローコールを再現できない場合、この機能はコードの実行とメソッドの呼び出しをシミュレートできます。
トレースにフレームワーク以外のレイヤーのメソッドとイベントトラッキングがない場合、この機能は、イベントトラッキングに関連するメソッドに費やされた時間を復元するのに役立ちます。
前提条件
ARMS エージェントは V3.1.4 以降です。
V4.2.1 より前: 同期呼び出しのみをサポートします。非同期呼び出しでは、データが欠落する可能性があります。たとえば、Spring Cloud Gateway、Undertow、または Lettuce を使用すると、スレッドが非同期に切り替えられ、データ収集の精度が低下する可能性があります。
V4.2.1 以降: 同期呼び出しと非同期呼び出しの両方をサポートします。
オペレーティングシステム カーネルと JDK のバージョンが要件を満たしていること。コード診断機能は、継続的プロファイリング機能に依存します。
コード診断機能を有効にする
ARMS console にログインします。左側のナビゲーションウィンドウで、 を選択します。
[アプリケーションリスト] ページで、上部のナビゲーションバーでリージョンを選択し、管理するアプリケーションの名前をクリックします。
説明[言語] 列に表示されるアイコンは、アプリケーションが記述されている言語を示します。
: Java アプリケーション
: Go アプリケーション
: Python アプリケーションハイフン (-): Managed Service for OpenTelemetry で監視されるアプリケーション。
左側のナビゲーションウィンドウで、[アプリケーション設定] をクリックします。表示されるページで、[カスタム設定] タブをクリックします。
[継続的プロファイリング] セクションで、[メインスイッチ] と [コードホットスポット] をオンにして、アプリケーションインスタンスの IP アドレスまたは複数のインスタンスの CIDR ブロックを設定します。
タブの下部にある [保存] をクリックします。
アプリケーションを再起動しなくても変更が有効になります。
[インターフェイス呼び出し] ページでホットスポットコードデータを表示する
例: JSON データを解析および走査し、ダウンストリーム HTTP インターフェイスを呼び出します。
public class HotSpotAction extends AbsAction {
private RestTemplate restTemplate = new RestTemplate();
// リクエストメソッド
@Override
public void runBusiness() {
readFile();
invokeAPI();
}
// HTTP 呼び出しを実行する
private void invokeAPI() {
String url = "https://httpbin.org/get";
String response = restTemplate.getForObject(url, String.class);
}
// ファイルデータを読み取って解析する
private double readFile() {
InputStreamReader reader = new InputStreamReader(
ClassLoader.getSystemResourceAsStream("data/xxx.json"));
LinkedList<Movie> movieList = GSON.fromJson(reader, new TypeToken<LinkedList<Movie>>() {
}.getType());
double totalCount = 0;
for (int i = 0; i < movieList.size(); i++) {
totalCount += movieList.get(i).rating();
}
return totalCount;
}
}ARMS console にログインします。左側のナビゲーションウィンドウで、 を選択します。
[アプリケーションリスト] ページで、上部のナビゲーションバーでリージョンを選択し、管理するアプリケーションの名前をクリックします。
説明[言語] 列に表示されるアイコンは、アプリケーションが記述されている言語を示します。
: Java アプリケーション
: Go アプリケーション
: Python アプリケーションハイフン (-): Managed Service for OpenTelemetry で監視されるアプリケーション。
左側のナビゲーションウィンドウで、インターフェイス呼び出しインターフェイスのスナップショット をクリックします。表示されるページで、インターフェースを選択し、 タブをクリックします。
[インターフェース スナップショット] タブで、トレース ID をクリックします。
[詳細] 列の [虫眼鏡] アイコン をクリックし、[コードホットスポット] タブをクリックします。

図の左側は、関連するすべてのメソッドに費やされた時間を示し、右側は、各メソッドのすべてのメソッドスタック情報のフレームグラフを示しています。
セルフ 列には、各メソッドがスタック内で消費する時間またはリソースが表示されます。子メソッドが消費する時間またはリソースは含まれません。このデータを使用すると、過剰な時間またはリソースを費やしているメソッドを特定できます。
[合計] 列には、各メソッドによって消費された時間またはリソース (すべての子メソッドで消費されたものを含む) が表示されます。このデータを使用して、最も多くの時間またはリソースを消費しているメソッドを特定できます。
コードロジックを分析する際には、[Self] 列または右側フレームグラフの下部にある幅の広いフレームに注目することで、時間のかかるメソッドを見つけることができます。一般的に、幅の広いフレームはシステムパフォーマンスのボトルネックを示します。前の図の java.lang.Thread.sleep() メソッドは、システムパフォーマンスのボトルネックが原因で多くの時間を消費しています。
前の図に基づいて、次の分析を実行します。
[Self] 列の値を昇順に並べ替えます。値が最も大きいメソッド java.util.LinkedList.node(int) を見つけてクリックします。関連するメソッドがフレームグラフに表示されます。

java.util.LinkedList.node(int) メソッドは、フレームグラフのスタックトップに最も幅の広いボックスを持っていることに注意してください。
java.util.LinkedList.node(int) メソッドは Java 開発キット (JDK) のライブラリ関数であるため、さらに上を検索すると、java.util.LinkedList.get(int) メソッドとその親メソッド com.alibaba.cloud.pressure.memory.HotSpotAction.readFile() が見つかります。アプリケーションによって定義された最初のサービスメソッドとして、com.alibaba.cloud.pressure.memory.HotSpotAction.readFile() メソッドは 3.75 秒を消費し、スタックの 69.88% を占めています。したがって、com.alibaba.cloud.pressure.memory.HotSpotAction.readFile() メソッドは、指定された期間に多くのリソースを消費していると結論付けることができます。ここで説明したメソッドを使用して、関連メソッドのロジックを分析し、最適化できるかどうかを確認できます。
よくある質問
コードに費やされた時間がリクエストに費やされた時間よりも短いのはなぜですか。
コード診断機能がアプリケーションのパフォーマンスに与える影響を最小限に抑えるため、データ収集を最適化しました。このようにして、表示される時間は実際の時間よりも短くなります。一般に、偏差は 20 ミリ秒以下です。絶対値の偏差は無視し、最も時間がかかるメソッドに焦点を当てることをお勧めします。
コード診断の統計には制限がありますか。
15 分を超えるリクエストの場合、コード診断機能は最初の 15 分の分析データのみを提供します。
システムのオーバーヘッドを削減するため、アプリケーション監視は 500 ミリ秒未満のリクエストのコードデータを収集しません。したがって、[ホットスポットコード] タブにデータが表示されない場合があります。
参考資料
継続的プロファイリング機能を使用する場合:
CPU 使用率とメモリ使用率が高い問題のトラブルシューティングについては、以下を参照してください。
よくある問題のトラブルシューティング。