本文適用於:✔️ .NET Core 3.1 SDK 和更新版本
在本教學課程中,您將瞭解如何偵錯 CPU 使用量過高的案例。 使用提供的 Core Web 應用程式 原始碼存放庫 ASP.NET 範例,您可以故意造成死結。 端點將停止回應並經歷執行緒累積。 您將瞭解如何使用各種工具,透過數個重要的診斷資料來診斷此案例。
在此教學課程中,您將會:
- 調查高 CPU 使用率
- 使用 dotnet-counters 判斷 CPU 使用量
- 使用 dotnet-trace 進行追蹤產生
- PerfView 中的設定檔效能
- 診斷並解決 CPU 使用率過高的問題
先決條件
本教學課程使用:
- .NET Core 3.1 SDK 或更新版本。
- 觸發案例的範例偵錯目標。
- dotnet-trace 來列出進程並產生設定檔。
- dotnet-counters 來監視 CPU 使用量。
CPU 計數器
在嘗試本教學課程之前,請先安裝最新版本的 dotnet-counters:
dotnet tool install --global dotnet-counters
如果您的應用程式執行的 .NET 版本早於 .NET 9,則 dotnet-counters 的輸出 UI 看起來會稍有不同;如需詳細資訊,請參閱 dotnet-counters 。
在嘗試收集診斷資料之前,您需要觀察高 CPU 狀況。 使用專案根目錄中的下列命令執行 範例應用程式 。
dotnet run
若要檢查目前的 CPU 使用量,請使用 dotnet-counters 工具命令:
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
輸出應類似下列內容:
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.109 0
user 0.453 0
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
重點關注 Last Delta 的值 dotnet.process.cpu.time,這些值告訴我們 CPU 在刷新期間(目前設置為默認值 1 秒)內有多少秒處於活動狀態。 當 Web 應用程式執行時,啟動後立即不會耗用 CPU,而且這些差異都是 0。 導航到 api/diagscenario/highcpu 路由,作為 60000 路由參數:
https://localhost:5001/api/diagscenario/highcpu/60000
現在,重新執行 dotnet-counters 命令。
dotnet-counters monitor -n DiagnosticScenarios --showDeltas
您應該會看到 CPU 使用率增加,如下所示 (視主機而定,預期 CPU 使用率會有所不同):
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value Last Delta
[System.Runtime]
dotnet.assembly.count ({assembly}) 111 0
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 8 0
gen1 1 0
gen2 0 0
dotnet.gc.heap.total_allocated (By) 4,042,656 24,512
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 801,728 0
gen1 6,048 0
gen2 0 0
loh 0 0
poh 0 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 811,512 0
gen1 562,024 0
gen2 1,095,056 0
loh 98,384 0
poh 24,528 0
dotnet.gc.last_collection.memory.committed_size (By) 5,623,808 0
dotnet.gc.pause.time (s) 0.019 0
dotnet.jit.compilation.time (s) 0.582 0
dotnet.jit.compiled_il.size (By) 138,895 0
dotnet.jit.compiled_methods ({method}) 1,470 0
dotnet.monitor.lock_contentions ({contention}) 4 0
dotnet.process.cpu.count ({cpu}) 22 0
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.344 0.013
user 14.203 0.963
dotnet.process.memory.working_set (By) 65,515,520 0
dotnet.thread_pool.queue.length ({work_item}) 0 0
dotnet.thread_pool.thread.count ({thread}) 0 0
dotnet.thread_pool.work_item.count ({work_item}) 6 0
dotnet.timer.count ({timer}) 0 0
在整個要求期間,CPU 使用率會徘徊在增加的值附近。
小提示
若要視覺化更高的 CPU 使用率,您可以同時在多個瀏覽器索引標籤中練習此端點。
此時,您可以肯定地說 CPU 的運行速度高於您的預期。 識別問題的影響是找到原因的關鍵。 除了診斷工具外,我們還將利用CPU消耗過高的影響來尋找問題的原因。
使用分析器分析高 CPU
分析 CPU 使用率較高的應用程式時,您需要一個診斷工具,以深入了解程式碼正在執行的動作。 通常的選擇是分析器,並且有不同的分析器選項可供選擇。
dotnet-trace 可以在所有作業系統上使用,不過,與核心感知分析器 (例如 Linux 的 'perf' 或 Windows 的 ETW) 相比,其安全點偏差和僅受管理呼叫堆疊的限制會導致更一般的資訊。 如果您的效能調查只涉及 Managed 程式碼, dotnet-trace 通常就足夠了。
此 perf 工具可用來產生 .NET Core 應用程式設定檔。 我們將示範此工具,不過也可以使用 dotnet-trace。 結束 範例偵錯目標的前一個實例。
設定DOTNET_PerfMapEnabled環境變數,讓 .NET 應用程式在目錄中map建立/tmp檔案。 此 map 檔案用於 perf 依名稱將 CPU 位址對應至 JIT 產生的函式。 如需詳細資訊,請參閱 匯出效能對應和 jit 傾印。
在相同的終端機工作階段中執行 範例偵錯目標 。
export DOTNET_PerfMapEnabled=1
dotnet run
再次練習高 CPU API 端點 (https://localhost:5001/api/diagscenario/highcpu/60000)。 當它在 1 分鐘請求內執行時, perf 請使用您的進程 ID 執行命令:
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 中進行分析。 若要在 Visual Studio 中分析 Linux *.nettrace 檔案,請將 *.nettrace 檔案以及其他必要的檔傳輸至 Windows 電腦,然後在 Visual Studio 中開啟 *.nettrace 檔案。 如需詳細資訊,請參閱 分析 CPU 使用量資料。
另請參閱
- dotnet-trace 來列出進程
- dotnet-counters 來檢查受控記憶體使用量
- dotnet-dump 來收集和分析傾印檔案
- dotnet/diagnostics