.NET 效能工程
當需要調查、解釋、修正、基準測試或驗證 .NET 應用程式(包括 ASP.NET Core、服務、主控台應用程式、Avalonia、WPF、WinUI、MAUI、Skia、WebGPU、遊戲/圖形引擎、NativeAOT 及原生互通性工作負載)的效能時,請使用此技能。
此儲存庫定義了一個技能。SKILL.md 是政策和路由的進入點;詳細的操作程序則位於階層式參考樹中。僅載入當前調查所需的索引和章節,然後在證據跨越所有權邊界時再進行擴展。
不可妥協的規則
- 分析並基準測試最佳化建置(通常為
Release),且須為真實的部署形式。 - 記錄提交狀態及髒狀態、SDK/執行階段、OS、架構、硬體、電源模式、工作負載、工具版本、環境覆寫以及確切指令。
- 在修改程式碼之前,建立可確定的再現步驟。
- 區分冷啟動、首次使用、熱穩定狀態、超載、耗盡及關機等階段。
- 預先暖機分層編譯、著色器、管線、快取和集區,除非冷行為是調查主題。
- 在每個相關的所有權邊界收集證據:受控執行階段、原生程式庫、核心、排程器、檔案系統/網路、相依性、驅動程式、GPU、合成器及顯示器。
- 請勿僅從 RSS 推斷受控記憶體保留。
- 請勿僅從高幀時間、GPU API 使用率或利用率推斷 GPU 飽和。
- 請勿僅根據一次平均值、一次追蹤、一次影格捕獲、一次微基準測試或最快的基準測試執行來聲稱已修正。
- 保留原始產出物,並回報遺失的符號、丟棄的事件、分析器開銷、環境變異性及不確定性。
- 保護傾印、追蹤、日誌、SQL 跨度、封包捕獲及基準測試輸入語料庫中的機密和個人資料。
- 將指令範例視為版本敏感。首先查詢已安裝工具的說明;當語法不同時,說明優先於範例。使用
references/command-reference.md來獲取經過驗證的選擇規則和規範形式。1
必要的調查輸出
報告:
- 症狀 — 可觀察的影響及違反的目標。
- 再現 — 確定的工作負載和環境。
- 收集 — 確切的工具、指令、持續時間及產出物路徑。
- 證據 — 計數器、追蹤、捕獲、傾印、基準測試分佈及測量值。
- 所有權 — 受控 CPU、執行階段、原生 CPU、核心、排程器、I/O、相依性、記憶體、驅動程式、GPU、合成器或顯示器。
- 主因 — 最大的已支援成本、等待時間或增長最快的資源。
- 修復 — 最小的高槓桿程式碼或設定變更。
- 驗證 — 等效的前/後執行結果,包含分佈範圍和尾部指標。
- 殘留風險 — 未解決的瓶頸和測量限制。
未提供前/後等效工作負載的證據,切勿聲稱任何改善。
參考資料路由器
始終從 references/index.md、references/core/index.md 以及經過驗證的 references/command-reference.md 開始。
根據問題載入其他領域索引:
- 受控 CPU、配置、GC、JIT、例外、ThreadPool、鎖、非同步堆疊、傾印:
references/runtime/index.md - 受控/原生/VM/對映/GPU 記憶體所有權及流失分析:
references/memory/index.md - 競爭、非同步延遲、佇列、背壓、檔案/網路/資料庫 I/O、UI 發送器延遲:
references/latency/index.md - 冷啟動、首個影格/請求、載入器、JIT、ReadyToRun、裁剪、單一檔案、NativeAOT:
references/startup/index.md - BenchmarkDotNet、微/元件/宏/負載/浸泡基準測試、非同步/並行基準測試、JIT/AOT 比較、反組譯、硬體計數器、統計資料、CI 閘道:
references/benchmarking/index.md - 生產環境、容器、診斷連接埠、
dotnet-monitor、觸發式收集、Kubernetes、產出物安全性:references/production/index.md - UI/渲染/GPU/WebGPU/Metal/D3D/Vulkan/OpenGL/著色器/同步/呈現:
references/gpu/index.md
透過 references/platforms/index.md 載入每個相關的平台參考。單一主機的調查通常需要一份平台文件;跨平台比較和遠端/客戶端-伺服器場景可能需要多份。
預設情況下不要載入所有文件。選擇能回答當前假設的最小集合,但不要僅因為需要另一份指南就在所有權邊界處停止。
快速分類序列
- 建置並執行與生產環境等效的設定。
- 定義工作負載階段、成功指標及停止規則。
- 記錄
System.Runtime計數器以及處理程序 CPU 和總記憶體。 - 當受控所有權合理時,使用
dotnet-trace捕獲受控 CPU/執行階段證據。 - 若懷疑有進展停滯、資源耗盡或封鎖情況,捕獲重複的堆疊。
- 若總成本無法解釋,收集平台原生 CPU/排程器/I/O/記憶體追蹤。
- 針對記憶體,比較受控活動位元組、GC 承諾量、私人/RSS/PSS、原生配置、對映、圖形配置及 GPU 駐留。
- 針對渲染,關聯應用程式標記、CPU 提交、GPU 時間戳記、原生 GPU 捕獲、呈現、合成器及顯示時序。
- 對於基準測試請求,在選擇 BenchmarkDotNet 或其他框架之前,先選擇微、元件、宏、負載或浸泡方法論。
- 對於僅限生產環境的事件,使用有限或觸發式收集,並記錄 cgroup/主機限制。
- 僅在證據支持主因後才實施修復。
- 重複相同的工作負載,並發佈中位數、分佈範圍、尾部值及原始產出物。
所有權測試
- 處理程序 CPU 高且受控堆疊熱:應用程式/JIT/執行階段工作。
- 處理程序 CPU 高但低於 P/Invoke:原生程式庫、配置器、圖形 API 或驅動程式 CPU。
- CPU 低但有重複的封鎖堆疊:同步、I/O、排程器、佇列或外部相依性。
- ThreadPool 佇列上升且 CPU 低且有封鎖堆疊:資源耗盡或同步-非同步轉換。
- 受控活動位元組穩定但私人/RSS 增長:原生堆積、對映、程式碼堆積、碎片、圖形資源或 OS 快取。
- 在等效的完整收集點後,受控活動圖仍在增長:受控記憶體保留或意圖不明的無界快取。
- CPU 幀時間長但 GPU 時間戳記短:應用程式/渲染執行緒/驅動程式 CPU 瓶頸。
- CPU 提交時間短但 GPU 時間戳記長:GPU 執行瓶頸。
- CPU 和 GPU 都提前完成但呈現延遲:交換鏈、合成器、垂直同步、繪製資源耗盡或顯示節奏。
- GPU 在相依提交之間有空閒間隔:CPU 資源耗盡、過度同步、序列化或緩衝不足。
- 高延遲但 CPU 運行時間低:非 CPU 等待、佇列、相依性、節流或排程器延遲。
- 啟動改進但首次操作變差:工作被延遲而非移除。
- 基準測試改進但產品指標未改進:實驗遺漏了關鍵路徑、使用了錯誤的輸入分佈,或最佳化了非主導操作。
代理程式操作程序
- 檢查儲存庫的建置、部署、診斷、基準測試專案、輸入語料庫、CI 及產出物慣例。
- 建立
artifacts/performance/<issue-or-timestamp>/或儲存庫的等效目錄。 - 當缺少時,新增一個確定的工作負載驅動程式和穩定的標記。
- 將指令、環境元資料、分析器/工具版本及官方參考連結儲存在產出物旁。
- 首先分析包含性成本,然後分析獨佔成本、被呼叫者、等待、佇列、同步及所有權。
- 僅在主因獲得支持後才修改程式碼。
- 新增一個能防止問題再次發生的基準測試、回歸預算、遙測標記、追蹤配方或生命週期不變量。
- 除非儲存庫政策明確允許,否則將大型追蹤、捕獲、傾印及基準測試產出物保留在 Git 之外。
- 驗證失敗、取消、超載、清理、設備遺失及關機路徑,而不僅僅是正常路徑。
應拒絕的無效結論
- 「CPU 很高,因此方法 X 很慢」但沒有堆疊資訊。
- 「RSS 增長了,因此受控堆積發生流失。」
- 「GC 堆積穩定,因此沒有流失。」
- 「平均延遲/幀時間在預算內,因此尾部指標健康。」
- 「GPU 使用率高,因此著色器 X 是瓶頸。」
- 「渲染執行緒忙碌,因此 GPU 也忙碌。」
- 「一個影格捕獲代表了穩定狀態的行為。」
- 「較少的繪圖呼叫總是意味著更快的渲染。」
- 「更多的 ThreadPool 執行緒可以修正資源耗盡。」
- 「非同步程式碼不會封鎖。」
- 「NativeAOT 自動更快。」
- 「微基準測試的改進證明了應用程式的改進。」
- 「統計上顯著的差異會自動轉化為產品上的顯著性。」
- 「一次基準測試執行就證明了結果。」
文件腳註
Footnotes
-
references/command-reference.md,其中連結到 .NET 診斷工具、BenchmarkDotNet、Xcode Instruments、Windows Performance Toolkit、Linuxperf/BCC、PresentMon、RenderDoc 及供應商 GPU 分析器的當前官方文件。 ↩