共用方式為


偵錯 .NET Core 中的高 CPU 使用量

本文適用於:✔️ .NET Core 3.1 SDK 和更新版本

在本教學課程中,您將瞭解如何偵錯 CPU 使用量過高的案例。 使用提供的 Core Web 應用程式 原始碼存放庫 ASP.NET 範例,您可以故意造成死結。 端點將停止回應並經歷執行緒累積。 您將瞭解如何使用各種工具,透過數個重要的診斷資料來診斷此案例。

在此教學課程中,您將會:

  • 調查高 CPU 使用率
  • 使用 dotnet-counters 判斷 CPU 使用量
  • 使用 dotnet-trace 進行追蹤產生
  • PerfView 中的設定檔效能
  • 診斷並解決 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 您可以在瀏覽器中檢視該檔案以調查效能問題:

火焰圖 SVG 影像

使用 Visual Studio 分析高 CPU 資料

所有 *.nettrace 檔案都可以在 Visual Studio 中進行分析。 若要在 Visual Studio 中分析 Linux *.nettrace 檔案,請將 *.nettrace 檔案以及其他必要的檔傳輸至 Windows 電腦,然後在 Visual Studio 中開啟 *.nettrace 檔案。 如需詳細資訊,請參閱 分析 CPU 使用量資料

另請參閱

後續步驟