使用 PerfCollect 追蹤 .NET 應用程式

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

在 Linux 上遇到效能問題時,可使用 perfcollect 來收集追蹤,以收集出現效能問題時的電腦狀況詳細資訊。

perfcollect 是 Bash 指令碼,其會使用 Linux Trace Toolkit: next generation (LTTng) 來收集從執行階段或任何 EventSource 寫入的事件,並使用 perf 來收集目標處理序的 CPU 樣本。

準備您的電腦

請遵循下列步驟來準備您的電腦,以使用 perfcollect 來收集效能追蹤。

注意

如果您要從容器內部擷取,則容器必須具備適當的功能。 基本的必要功能是 PERFMONSYS_PTRACE。 如果基本的功能集會讓擷取失敗,請在容器中新增 SYS_ADMIN 功能。 如需使用 PerfCollect 追蹤容器內應用程式的詳細資訊,請參閱收集容器中的診斷

  1. 下載 perfcollect

    curl -OL https://aka.ms/perfcollect
    
  2. 讓指令碼成為可執行檔。

    chmod +x perfcollect
    
  3. 安裝追蹤必要項目 - 這些是實際的追蹤程式庫。

    sudo ./perfcollect install
    

    這會在您的電腦上安裝下列必要項目:

    1. perf:Linux 效能事件子系統和隨附的使用者模式集合/檢視器應用程式。 perf 是 Linux 核心來源的一部分,但通常不會預設安裝。

    2. LTTng:用於擷取 CoreCLR 在執行階段發出的事件資料。 然後,此資料可用於分析各種執行階段元件的行為,例如 GC、JIT 和執行緒集區。

最新版 .NET Core 和 Linux perf 工具支援自動解析架構程式碼的方法名稱。

如需解析原生執行階段 DLL 的方法名稱 (例如 libcoreclr.so),perfcollect 會在轉換資料時解析其符號,但前提是這些二進位檔的符號存在。 如需詳細資訊,請參閱取得原生執行階段符號一節。

收集追蹤

  1. 有兩個殼層可供使用,一個用於控制追蹤,稱為 [Trace],另一個用於執行應用程式,稱為 [App]

  2. [Trace] 開始收集。

    sudo ./perfcollect collect sampleTrace
    

    預期輸出:

    Collection started.  Press CTRL+C to stop.
    
  3. [App] 使用下列環境變數設定應用程式殼層,這會啟用 CoreCLR 的追蹤組態。

    export DOTNET_PerfMapEnabled=1
    export DOTNET_EnableEventLog=1
    

    注意

    使用 .NET 7 執行應用程式時,除了上述環境變數之外,您也必須設定 DOTNET_EnableWriteXorExecute=0。 例如:

    export DOTNET_EnableWriteXorExecute=0
    

    注意

    .NET 6 會針對設定 .NET Runtime 行為的環境變數,透過前置詞 DOTNET_ (而非 COMPlus_) 進行標準化。 不過,COMPlus_ 前置詞將繼續運作。 如果使用舊版的 .NET 執行階段,則您仍應對環境變數使用 COMPlus_ 前置詞。

  4. [App] 執行應用程式;請依所需的時間執行以擷取效能問題。 只要足以擷取發生所要調查效能問題的時間範圍,確切的時間就可以非常簡短。

    dotnet run
    
  5. [Trace] 停止收集,請按 CTRL+C。

    ^C
    ...STOPPED.
    
    Starting post-processing. This may take some time.
    
    Generating native image symbol files
    ...SKIPPED
    Saving native symbols
    ...FINISHED
    Exporting perf.data file
    ...FINISHED
    Compressing trace files
    ...FINISHED
    Cleaning up artifacts
    ...FINISHED
    
    Trace saved to sampleTrace.trace.zip
    

    壓縮的追蹤檔案現在會儲存在目前的工作目錄中。

檢視追蹤

有數個選項可用來檢視已收集的追蹤。 最適合使用 Windows 上的 PerfView 來檢視追蹤,但也可以使用 PerfCollect 本身或 TraceCompass 直接在 Linux 上檢視追蹤。

使用 PerfCollect 檢視追蹤檔案

您可以使用 perfcollect 本身來檢視收集的追蹤。 若要這麼做,請使用下列命令:

./perfcollect view sampleTrace.trace.zip

根據預設,這會使用 perf 來顯示應用程式的 CPU 追蹤。

若要查看透過 LTTng 收集的事件,您可以傳入 -viewer lttng 旗標以查看個別事件:

./perfcollect view sampleTrace.trace.zip -viewer lttng

這會使用 babeltrace 檢視器來列印事件承載:

# [01:02:18.189217659] (+0.020132603) ubuntu-xenial DotNETRuntime:ExceptionThrown_V1: { cpu_id = 0 }, { ExceptionType = "System.Exception", ExceptionMessage = "An exception happened", ExceptionEIP = 139875671834775, ExceptionHRESULT = 2148734208, ExceptionFlags = 16, ClrInstanceID = 0 }
# [01:02:18.189250227] (+0.020165171) ubuntu-xenial DotNETRuntime:ExceptionCatchStart: { cpu_id = 0 }, { EntryEIP = 139873639728404, MethodID = 139873626968120, MethodName = "void [helloworld] helloworld.Program::Main(string[])", ClrInstanceID = 0 }

使用 PerfView 開啟追蹤檔案

若要查看 CPU 範例和事件的彙總檢視,您可以在 Windows 電腦上使用 PerfView

  1. 將 trace.zip 檔案從 Linux 複製到 Windows 電腦。

  2. https://aka.ms/perfview 下載 PerfView。

  3. 執行 PerfView.exe

    PerfView.exe <path to trace.zip file>
    

PerfView 會根據追蹤檔案中包含的資料,顯示支援的檢視清單。

  • 針對 CPU 調查,請選擇 CPU 堆疊

  • 如需詳細的 GC 資訊,請選擇 GCStats

  • 針對每個處理序/模組/方法 JIT 資訊,請選擇 JITStats

  • 如果沒有所需資訊的檢視,您可以嘗試在原始事件檢視中尋找事件。 選擇 Events

如需如何在 PerfView 中解譯檢視的詳細資訊,請參閱檢視本身的說明連結,或在 PerfView 的主視窗選擇 [Help->Users Guide]

注意

透過 System.Diagnostics.Tracing.EventSource API 撰寫的事件 (包括來自 Framework 的事件) 不會顯示在提供者名稱下。 相反地,它們會寫入為 Microsoft-Windows-DotNETRuntime 提供者下的 EventSourceEvent 事件,且其承載會序列化為 JSON。

注意

如果您會觀察方法名稱和呼叫堆疊中的 [unknown] /memfd:doublemapper 框架,請先設定 DOTNET_EnableWriteXorExecute=0,再執行以 perfcollect 追蹤的應用程式。

使用 TraceCompass 開啟追蹤檔案

Eclipse TraceCompass 是可用來檢視追蹤的另一個選項。 TraceCompass 也適用於 Linux 機器,因此不需要將追蹤移至 Windows 電腦。 若要使用 TraceCompass 開啟追蹤檔案,您必須將檔案解壓縮。

unzip myTrace.trace.zip

perfcollect 會將其收集的 LTTng 追蹤儲存為 lttngTrace 內子目錄中的 CTF 檔案格式。 具體而言,CTF 檔案會位於類似 lttngTrace/auto-20201025-101230\ust\uid\1000\64-bit\ 的目錄中。

您可以依序選取 File -> Open Tracemetadata 檔案,以在 TraceCompass 中開啟 CTF 追蹤檔案。

如需詳細資料,請參閱 TraceCompass 文件

取得原生執行階段的符號

您在大部分時間內都會對自己的程式碼感興趣,而 perfcollect 預設會解析這些程式碼。 有時候,查看 .NET DLL 內發生的狀況會很有用 (此為最後一節的內容);但有時,原生執行階段 DLL (通常是 libcoreclr.so) 中發生的狀況才是您該感興趣的。 perfcollect 會在轉換其資料時解析這些符號,但前提是這些原生 DLL 的符號必須存在 (且位於使用它們的程式庫旁)。

名為 dotnet-symbol 的全域命令會執行這項作業。 若要使用 dotnet-symbol 來取得原生執行階段符號:

  1. 安裝 dotnet-symbol

    dotnet tool install -g dotnet-symbol
    
  2. 下載符號。 如果您已安裝的 .NET Core 執行階段版本為 2.1.0,則執行這項作業的命令為:

    mkdir mySymbols
    dotnet symbol --symbols --output mySymbols  /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0/lib*.so
    
  3. 將符號複製到正確的位置。

    sudo cp mySymbols/* /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0
    

    如果因為沒有適當目錄的寫入權限而無法執行此動作,則可使用 perf buildid-cache 來新增符號。

在此之後,您應該會在執行 perfcollect 時取得原生 DLL 的符號名稱。

在 Docker 容器中收集

如需如何在容器環境中使用 perfcollect 的詳細資訊,請參閱在容器中收集診斷

深入了解收集選項

您可以使用 perfcollect 來指定下列選擇性旗標,以更加符合診斷需求。

在特定持續時間內收集

當您想要在特定持續時間內收集追蹤時,可以使用 -collectsec 選項,後面接著指定收集追蹤所用總秒數的數字。

收集 threadtime 追蹤

使用 perfcollect 指定 -threadtime 可讓您收集每個執行緒的 CPU 使用方式資料。 這可讓您分析每個執行緒會在哪些位置耗用 CPU 時間。

收集對受控記憶體和記憶體回收行程效能的追蹤

下列選項可讓您特別從執行階段收集 GC 事件。

  • perfcollect collect -gccollectonly

只收集一組最少的 GC 收集事件。 這是最粗略的 GC 事件收集設定檔,對目標應用程式效能的影響最低。 此命令類似於 PerfView 中的 PerfView.exe /GCCollectOnly collect 命令。

  • perfcollect collect -gconly

使用 JIT、載入器和例外狀況事件收集更詳細的 GC 收集事件。 這會要求更詳細的事件 (例如配置資訊和 GC 聯結資訊),且會對目標應用程式效能產生比 -gccollectonly 更大的影響。 此命令類似於 PerfView 中的 PerfView.exe /GCOnly collect 命令。

  • perfcollect collect -gcwithheap

會收集最詳細的 GC 收集事件,這可追蹤堆積的存續和移動。 這可提供 GC 行為的深入分析,但因為每個 GC 可能需要兩倍以上的時間來處理,所以會產生較高的效能成本。 建議您了解在生產環境中追蹤時,使用此追蹤選項的效能影響。