共用方式為


案例研究:隔離效能問題(C#、Visual Basic、F#)

此案例研究示範如何使用 Visual Studio 分析工具來識別和解決範例 ASP.NET 應用程式中的效能問題。 如需分析工具的比較,請參閱 我應該選擇哪一個工具?

您將了解:

  • 如何使用 Visual Studio 分析工具來分析應用程式效能。
  • 如何分析剖析數據以尋找瓶頸。
  • 使用 .NET 計數器、呼叫計數和計時數據優化程式代碼的實際策略。

套用這些技術來改善您自己的應用程式。

找出效能問題案例研究

範例 ASP.NET 應用程式會針對模擬資料庫執行查詢,並且以 診斷範例為基礎。

主要效能徵兆:

  • 低 CPU 使用量:CPU 不是瓶頸。
  • 高線程集區線程計數:線程計數會穩步上升,表示線程集區耗盡。
  • 應用程式回應緩慢:應用程式因缺乏可用的線程而回應緩慢。

此案例研究會使用 Visual Studio 分析工具來找出並解決這些問題,協助您讓您的程式代碼更快且更有效率。

挑戰

修正這些問題牽涉到數個挑戰:

  • 診斷瓶頸:CPU使用量低且效能緩慢可能由多種原因造成。 有效使用分析工具並解譯其輸出至關重要。
  • 知識和資源限制:分析與優化需要特定的技能和經驗,這不一定一定可供使用。

結合分析工具、技術知識和仔細測試的策略方法,是克服這些挑戰的關鍵。

策略

以下是此案例研究中方法的高階檢視:

  • 從監視 .NET 計數器計量開始,同時收集效能數據。 Visual Studio 的 .NET 計數器 工具是不錯的起點。
  • 如需更深入的深入解析,請使用其他分析工具收集追蹤,例如用於呼叫計數和計時數據的 檢測 工具。

資料收集需要下列工作:

  • 將應用程式設定為發行版本。
  • 在 [效能分析工具] 中選取 .NET 計數器工具 (Alt+F2)。
  • 啟動應用程式並收集追蹤記錄。

檢查性能計數器

執行應用程式時,我們會觀察 .NET 計數器工具中的計數器。 針對初始調查,一些要留意的重要計量包括:

  • CPU Usage。 觀看此計數器以確定效能問題是否在高或低 CPU 使用率下發生。 這可以是特定效能問題的線索。 例如:
    • 使用高 CPU 使用量時,請使用 CPU 使用量工具來識別我們或許能夠將程式代碼優化的區域。 如需此教學的教程,請參閱 案例研究:給初學者的程式代碼優化指南
    • 使用低 CPU 使用量時,使用檢測工具來根據時鐘時間識別呼叫計數和平均函式時間。 這有助於識別諸如競爭或執行緒池飢餓等問題。
  • Allocation Rate。 針對提供要求的 Web 應用程式,速率應該相當穩定。
  • GC Heap Size。 請觀看此計數器,以查看記憶體使用量是否持續增加且可能流失。 如果看起來很高,請使用其中一個記憶體使用量工具。
  • Threadpool Thread Count。 針對提供要求的 Web 應用程式,請觀看此計數器,以查看線程計數是否保持穩定或以穩定速率上升。

以下範例顯示 CPU Usage 低,而 ThreadPool Thread Count 相對較高。

.NET 計數器工具中顯示的計數器螢幕快照。

低 CPU 使用量的穩步上升線程計數可能是線程集區饑餓的指標。 線程池被迫不斷生成新線程。 當集區沒有可用的線程來處理新的工作專案,而且通常會造成應用程式回應緩慢時,就會發生線程集區饑餓。

根據低 CPU 使用量和相對較多的執行緒數量,基於可能出現的執行緒池資源匱乏問題的理論,切換至使用分析工具。

調查通話計數和計時數據

讓我們看看檢測工具的追蹤,看看我們是否可以嘗試深入了解線程發生的情況。

使用檢測工具收集追蹤並將其載入Visual Studio之後,我們會先檢查初始 .diagsession 報表頁面,其中顯示摘要數據。 在收集的追蹤中,我們使用報表中的 [開啟詳細資料] 連結,然後選取 [火焰圖]。

檢測工具中火焰圖形的螢幕快照。

Flame Graph 視覺效果顯示,QueryCustomerDB 函式(以黃色顯示)負責應用程式運行時間的很大一部分。

以滑鼠右鍵按兩下 QueryCustomerDB 函式,然後選擇 [呼叫樹狀結構] 中的 [檢視]。

工具中呼叫樹狀結構的螢幕快照。

應用程式中 CPU 使用量最高的程式代碼路徑稱為 熱路徑。 經常性路徑火焰圖示 (顯示經常性路徑圖示的螢幕快照。)可協助快速識別可能改善的效能問題。

在 [呼叫樹狀結構 檢視] 中,您可以看到熱門路徑包含 QueryCustomerDB 函式,這表明潛在的效能問題。

相對於其他函式所花費的時間,Self 值很高。 與 TotalAvg Total不同,Self 值會排除在其他函式中花費的時間,因此這是尋找效能瓶頸的好位置。

提示

如果 Self 值相對較低,而不是高值,您可能想要查看 QueryCustomerDB 函式所呼叫的實際查詢。

按兩下 QueryCustomerDB 函式以顯示函式的原始程式碼。

public ActionResult<string> QueryCustomerDB()
{
    Customer c = QueryCustomerFromDbAsync("Dana").Result;
    return "success:taskwait";
}

我們做了一些研究。 或者,我們可以節省時間,讓 科皮洛特 為我們做研究。

如果我們使用 Copilot,請從操作功能表中選取 [詢問 Copilot],然後輸入下列問題:

Can you identify a performance issue in the QueryCustomerDB method?

提示

您可以使用斜線命令來協助形成 Copilot 的良好問題,例如 /optimize

Copilot 告訴我們,此程式代碼在不使用 await 的情況下呼叫異步 API。 這是 同步包覆異步 程式代碼模式,這是執行緒池耗盡的常見原因,而且可能會封鎖執行緒。

若要解決問題,請使用 await。 在此範例中,Copilot 會提供下列程式代碼建議以及說明。

public async Task<ActionResult<string>> QueryCustomerDB()
{
    Customer c = await QueryCustomerFromDbAsync("Dana");
    return "success:taskwait";
}

如果您看到與資料庫查詢相關的效能問題,您可以使用 Database 工具 來調查特定呼叫是否較慢。 此數據可能表示有機會優化查詢。 如需示範如何使用資料庫工具來調查效能問題的教學課程,請參閱 案例研究:將程式代碼優化的初學者指南。 資料庫工具支援 .NET Core,並且可以使用 ADO.NET 或 Entity Framework Core。

若要在 Visual Studio 中取得個別線程行為的視覺效果,您可以在偵錯時使用 平行堆疊 視窗。 此視窗會顯示個別線程、正在等待的線程、其所等待的線程,以及 死結的相關信息。

如需瞭解執行緒集區資源不足的其他資訊,請參閱 偵測執行緒集區資源不足

後續步驟

下列文章和部落格文章提供詳細資訊,可協助您瞭解如何有效地使用 Visual Studio 效能工具。