本文适用于: ✔️ .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,請在指令中指定 System.Runtime[cpu-usage]。
dotnet-counters monitor --counters System.Runtime[cpu-usage] -p 22884 --refresh-interval 1
你将看到 CPU 使用率已增加,如下所示:
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
CPU Usage (%) 25
在整個請求期間,CPU 使用率将徘徊在 25% 左右。 根據主機的不同,預期 CPU 使用率會有所不同。
提示
若要可視化更高的 CPU 使用率,可以在多個浏覽器頁籤中同時使用此終結點。
此時,你可以放心地說 CPU 運作的速度比預期的要高。
跟蹤生成
當分析速度較慢的請求時,需要一個診斷工具來提供代碼正在執行的操作的見解。 常見的選擇是探查器,并且有不同的探查器選項可供選擇。
Linux
Windows
perf 工具可用于生成 .NET Core 應用配置檔案。 退出示例調試目标的上一個執行個體。
設定 DOTNET_PerfMapEnabled 環境變量,使 .NET Core 應用在 /tmp 目錄中建立 map 檔案。 perf 使用此 map 檔案按名稱将 CPU 位址映射到 JIT 生成的函數。 有關詳細資訊,請參閱寫入 Perf 映射。
備注
.NET 6 為用于配置 .NET 運作時行為的環境變量标準化字首 DOTNET_ 而不是 COMPlus_。 但是,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
還可以使用以下指令生成 flame-graph:
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
此指令生成 flamegraph.svg,你可以在浏覽器中檢視 flamegraph.svg 以調查性能問題:
在 Windows 上,可以使用 dotnet-trace 工具作為探查器。 使用之前的示例調試目标,再次使用高 CPU (https://localhost:5001/api/diagscenario/highcpu/60000) 終結點。 當它在 1 分鐘請求内運作時,使用 collect 指令,如下所示:
dotnet-trace collect -p 22884 --providers Microsoft-DotNETCore-SampleProfiler
讓 dotnet-trace 運作大約 20-30 秒,然後按 Enter 退出收集。 結果是位于同一檔案夾中的 nettrace 檔案。 nettrace 檔案是在 Windows 上使用現有分析工具的好方法。
使用 PerfView 打開 nettrace,如下所示。
請參閱
用于列出程序的 dotnet-trace
用于檢查托管記憶體使用情況的 dotnet-counters
用于收集和分析轉儲檔案的 dotnet-dump
dotnet/diagnostics
後續步驟
調試 .NET Core 中的死鎖