針對 .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
若要尋找處理序識別碼,請使用下列命令:
dotnet-trace ps
記下命令輸出中的處理序識別碼。 我們的處理序識別碼是 22884
,但您的處理序識別碼將會不同。 若要檢查目前 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
檔案。 perf
使用此 map
檔案,以依名稱將 CPU 位址對應至 JIT 產生的函數。 如需詳細資訊,請參閱匯出效能對應和 jit 傾印。
注意
.NET 6 會針對設定 .NET Runtime 行為的環境變數,透過前置詞 DOTNET_
(而非 COMPlus_
) 進行標準化。 不過,COMPlus_
前置詞將繼續運作。 如果使用舊版的 .NET 執行階段,則您仍應對環境變數使用 COMPlus_
前置詞。
在相同的終端機工作階段中,執行範例偵錯目標。
export DOTNET_PerfMapEnabled=1
dotnet run
再次執行高 CPU API 端點 (https://localhost:5001/api/diagscenario/highcpu/60000
)。 其在 1 分鐘要求內執行時,請使用您的處理序識別碼來執行 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
:
使用 Visual Studio 來分析高 CPU 資料
所有 *.nettrace 檔案都可以在 Visual Studio 中進行分析。 若要在 Visual Studio 中分析 Linux *.nettrace 檔案,除了其他必要文件之外,還會將 *.nettrace 檔案傳送至 Windows 機器,然後在 Visual Studio 中開啟 *.nettrace 檔案。 如需詳細資訊,請參閱分析 CPU 使用量資料。
另請參閱
- dotnet-trace,以列出處理序
- dotnet-counters 以檢查受控記憶體使用量
- dotnet-dump 以收集和分析傾印檔案
- dotnet/diagnostics (英文)