針對 .NET Core 中的高 CPU 使用量進行偵錯

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

在本教學課程中,您將了解如何針對過多 CPU 使用量情節進行偵錯。 使用提供的範例 ASP.NET Core Web 應用程式原始程式碼存放庫,就可以刻意造成死結。 端點將會停止回應,並發生執行緒累積。 您將了解如何使用各種工具,以利用數個重要診斷資料片段來診斷此情節。

在此教學課程中,您需要:

  • 調查高 CPU 使用量
  • 使用 dotnet-counters 來判斷 CPU 使用量
  • 使用 dotnet-trace 來產生追蹤
  • PerfView 中的設定檔效能
  • 診斷並解決過多的 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

Flame graph SVG image

使用 Visual Studio 來分析高 CPU 資料

所有 *.nettrace 檔案都可以在 Visual Studio 中進行分析。 若要在 Visual Studio 中分析 Linux *.nettrace 檔案,除了其他必要文件之外,還會將 *.nettrace 檔案傳送至 Windows 機器,然後在 Visual Studio 中開啟 *.nettrace 檔案。 如需詳細資訊,請參閱分析 CPU 使用量資料

另請參閱

下一步