Dot-Net
在 .Net 生產應用程序中診斷失控的 CPU
有誰知道可以幫助我弄清楚為什麼我們在託管應用程序中看到 CPU 失控的工具?
我不是在尋找什麼:
- 程序資源管理器,它有這個很棒的功能,可以讓您查看每個執行緒的 CPU,但您不會獲得託管堆棧跟踪。此外,它需要一個相當熟練的使用者。
- Windbg + SOS,它可能用於通過抓取一堆轉儲來弄清楚發生了什麼。但自動化並非易事,而且為此有點繁重。
- 完全成熟的分析器(如 dottrace 或 redgate),許可很複雜,而且該工具是一種過度殺傷,需要相當繁重的安裝。
我在找什麼:
- 我可以發送給客戶的一個簡單的 exe(沒有安裝程序)。在他們執行 10 分鐘後,它會生成一個他們發送給我的文件。該文件包含有關在此期間消耗最多 CPU 的執行緒及其堆棧跟踪的詳細資訊。
從技術上講,我知道可以創建這樣的工具(使用 ICorDebug),但如果這樣的工具已經存在,我不想投入任何時間。
那麼,有人知道這樣的事情嗎?
基本解決方案
- 獲取每個託管執行緒的託管堆棧跟踪。
- 獲取每個託管執行緒的基本執行緒統計資訊(使用者模式和核心時間)
- 稍等一會
- 重複 (1-3)
- 分析結果,找出消耗cpu使用量最大的執行緒,將這些執行緒的堆棧跟踪呈現給使用者。
託管VS。未管理的堆棧跟踪
託管和非託管堆棧跟踪之間存在很大差異。託管堆棧跟踪包含有關實際 .Net 呼叫的資訊,而非託管堆棧跟踪包含非託管函式指針列表。由於 .Net 是 jitted 的,因此在診斷託管應用程序的問題時,非託管函式指針的定址幾乎沒有用處。
如何獲得任意 .Net 程序的非託管堆棧跟踪?
有兩種方法可以獲得託管應用程序的託管堆棧跟踪。
- 使用 CLR 分析(又名 ICorProfiler API)
- 使用 CLR 調試(又名 ICorDebug API)
生產中什麼更好?
CLR 調試 API 比分析 API 有一個非常重要的優勢,它們允許您附加到正在執行的程序。在診斷生產中的性能問題時,這可能很關鍵。由於某些意外的程式碼分支執行,在應用程序使用數天后,經常會出現失控的 CPU。在那個時候重新啟動應用程序(為了分析它)不是一個選項。
cpu分析器.exe
因此,我編寫了一個無需安裝程序的小工具,並使用 ICorDebug 執行上述基本解決方案。它基於mdbg 源,它全部合併到一個 exe 中。
它以可配置的時間間隔(預設為 1000 毫秒)為所有託管執行緒採用可配置(預設為 10)數量的堆棧跟踪。
這是一個範例輸出:
C:\>cpu-analyzer.exe evilapp ------------------------------------ 4948 核心時間:0 使用者時間:89856576 EvilApp.Program.MisterEvil EvilApp.Program.b__0 System.Threading.ExecutionContext.Run System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal System.Threading._ThreadPoolWaitCallback.PerformWaitCallback ...更多數據省略...隨意試一試該工具。可以從我的部落格下載。
編輯
這是一個執行緒,展示了我如何使用 cpu-analyzer 在生產應用程序中診斷此類問題。
