.NET Core で高い CPU 使用率をデバッグする
この記事の対象: ✔️ .NET Core 3.1 SDK 以降のバージョン
このチュートリアルでは、過剰な CPU 使用率のシナリオをデバッグする方法について説明します。 示されている例の ASP.NET Core Web アプリ ソース コード リポジトリを使用して、デッドロックを意図的に発生させることができます。 エンドポイントは応答を停止し、スレッドが累積されます。 さまざまなツールを使用して、診断データのいくつかの重要な部分でこのシナリオを診断する方法について説明します。
このチュートリアルでは、次の作業を行います。
- 高い CPU 使用率を調査する
- dotnet-counters を使って CPU 使用率を確認する
- dotnet-trace を使ってトレース生成を行う
- PerfView でパフォーマンスをプロファイリングする
- 過剰な CPU 使用率を診断して解決する
必須コンポーネント
このチュートリアルでは次のものを使用します。
- .NET Core 3.1 SDK 以降のバージョン。
- シナリオをトリガーするサンプル デバッグ ターゲット
- dotnet-trace を使ってプロセスを一覧表示し、プロファイルを生成する
- dotnet-counters を使って CPU 使用率を監視する
CPU カウンター
診断データの収集を試行する前に、高い CPU 状態を確認する必要があります。 プロジェクトのルート ディレクトリから次のコマンドを使用して、サンプル アプリケーションを実行します。
dotnet run
このプロセス ID を検索するには、次のコマンドを使用します。
dotnet-trace ps
ご自分のコマンド出力からプロセス ID をメモしておきます。 プロセス ID は 22884
でしたが、この ID は異なります。 現在の CPU 使用率を確認するには、dotnet-counters ツール コマンドを使用します。
dotnet-counters monitor --refresh-interval 1 -p 22884
refresh-interval
は、CPU 値をポーリングするカウンターの間隔を秒数で示します。 出力は次のようになります。
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 0
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
Web アプリを実行している状態で、スタートアップ直後に CPU が使用されておらず、0%
で報告されます。 ルート パラメーターとして 60000
を使用して api/diagscenario/highcpu
ルートに移動します。
https://localhost:5001/api/diagscenario/highcpu/60000
次に、dotnet-counters コマンドを再実行します。 cpu-usage
カウンターのみを監視する場合は、前のコマンドに '--counters System.Runtime[cpu-usage]' を追加します。 CPU が使用されているかどうかは不明であるため、上記と同じカウンターの一覧を監視して、カウンター値がアプリケーションに予期される範囲内であることを確認します。
dotnet-counters monitor -p 22884 --refresh-interval 1
次に示すように、CPU 使用率の増加が表示されます (ホスト マシンにより、さまざまな CPU 使用率が想定されます)。
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 25
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
要求の期間中、CPU 使用率は上昇したパーセンテージで推移します。
ヒント
さらに高い CPU 使用率を視覚化するには、複数のブラウザー タブでこのエンドポイントを同時に実行します。
この時点で、CPU が予想以上に高くなっていることを確認できます。 問題の影響を特定することは、原因を見つけるための鍵となります。 診断ツールに加えて、高い CPU 使用率の影響を使って、問題の原因を見つけます。
プロファイラーで高い CPU 使用率を分析する
高い CPU 使用率のアプリを分析する場合は、コードの実行内容に関する分析情報を提供できる診断ツールが必要です。 通常はプロファイラーが適しており、さまざまなプロファイラー オプションを選択できます。 dotnet-trace
はすべてのオペレーティング システムで使用できますが、セーフポイント バイアスとマネージドのみの呼び出し履歴の制限により、Linux の 'perf' や Windows の ETW などのカーネルを認識するプロファイラーと比較すると、より一般的な情報になります。 パフォーマンス調査がマネージド コードのみであれば、通常、dotnet-trace
で十分です。
perf
ツールを使用すると、.NET Core アプリ プロファイルを生成できます。 ここではこのツールを示しますが、dotnet-trace も同様に使用できます。 サンプル デバッグ ターゲットの前のインスタンスを終了します。
DOTNET_PerfMapEnabled
環境変数を設定して、.NET アプリによって /tmp
ディレクトリ内に map
ファイルが作成されるようにします。 この map
ファイルは、CPU アドレスを名前順に JIT 生成関数にマップするために perf
によって使用されます。 詳細については、「perf マップと jit ダンプをエクスポートする」を参照してください。
Note
.NET 6 では、.NET の実行時の動作を構成する環境変数のプレフィックスが、COMPlus_
ではなく DOTNET_
に標準化されています。 ただし、プレフィックス COMPlus_
は引き続き機能します。 以前のバージョンの .NET ランタイムを使用している場合は、環境変数に COMPlus_
プレフィックスをまだ使用する必要があります。
同じターミナル セッションで、サンプル デバッグ ターゲットを実行します。
export DOTNET_PerfMapEnabled=1
dotnet run
高 CPU API エンドポイント (https://localhost:5001/api/diagscenario/highcpu/60000
) をもう一度実行します。 それが 1 分間の要求内で実行されている間に、プロセス ID を使用して perf
コマンドを実行します。
sudo perf record -p 2266 -g
perf
コマンドを実行すると、パフォーマンス コレクション プロセスが開始されます。 約 20 から 30 秒間実行してから、Ctrl + C キーを押してコレクション プロセスを終了します。 同じ perf
コマンドを使用して、トレースの出力を確認できます。
sudo perf report -f
次のコマンドを使用して "フレーム グラフ" を生成することもできます。
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
このコマンドを実行すると、flamegraph.svg
が生成され、これをブラウザーに表示してパフォーマンスの問題を調査することができます。
Visual Studio で高い CPU 使用率データを分析する
すべての *.nettrace ファイルは、Visual Studio で分析することができます。 Linux の *.nettrace ファイルを Visual Studio で分析するには、*.nettrace ファイルとその他の必要なドキュメントを Windows マシンに転送し、*.nettrace ファイルを Visual Studio で開いてください。 詳細については、「CPU 使用率データを分析する」を参照してください。
関連項目
- dotnet-trace を使ってプロセスを一覧表示する
- dotnet-counters を使ってマネージド メモリ使用量を確認する
- dotnet-dump を使ってダンプ ファイルを収集して分析する
- dotnet/診断
次の手順
.NET