中文:http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/enterpriseperformance.mspx?mfr=true
John Robbins
本文基于 Visual Studio 2005 的預發布版本。文中包含的所有信息均有可能變更。
本文討論:
? | 分析器的內部工作方式 |
? | EPT 的靈活功能 |
? | 一個供分析的示例應用程序 |
代碼可從以下位置下載:
EnterprisePerformance.exe (258KB)
快速代碼仍然很受歡迎。即使我用來鍵入本文的計算機具有足夠的能力和內存,能夠同時控制一座原子能發電廠、一個火星漫游計劃以及美國西部上空的空中交通,并且仍然具有充足的能力來處理星際探索中的 SETI 數據包,但這并不意味著開發人員不再需要擔心其代碼的速度和效率。在過去進行 Win32? 本機開發的日子里,我們不僅需要擔心速度,而且還要擔心 PC 平臺上那些令人討厭的訪問沖突(對于你們這些老家伙,還有“全局保護錯誤”和“不可恢復的應用程序錯誤”)。盡管托管代碼已經消除了其中的一些擔心,但它只意味著您所經歷的那些性能問題可能比以前更加難以捉摸。主要原因是,在使用托管代碼時,我們不具有在進行本機開發時所擁有的簡便的運行庫視圖。
有許多次,當我正在使用客戶端時,我不知道如何解決惡性的性能問題。當然,這些性能問題不會出現在任何測試系統中;它們只會出現在真實世界的生產中。由于公共語言運行庫 (CLR) 是黑盒,因此如果我希望找到在測試系統中重復性能問題的方法,則很難預測會發生什么事情。盡管在市場中有一些第三方商業性能工具,但這些工具中的大多數都會對系統造成過多的干擾,以至于根本不能考慮在生產系統中使用。這也就是當我看到 Microsoft 將提供一個全新的分析器 — Enterprise Performance Tool (EPT) 以作為 Visual Studio? 2005 Team Developer Edition 的一部分時,感到如此興奮的原因。它是我可以真正考慮在生產系統中使用的第一個分析系統,因為它提供了一些非常輕便的收集性能數據的手段。因為我曾經領導過一種最暢銷的商業分析器的開發工作,所以我能夠理解在不產生太多系統開銷的情況下收集有用分析數據的困難程度。
在本文中,我將介紹 EPT 的基本原理,并向您說明如何開始使用它。因為分析器所具有的復雜性,所以在將來某一期中,我將討論如何使用 EPT 來跟蹤您可能在同事的代碼中遇到的實際性能問題(我知道您的代碼非常完美?。?。請記住,EPT 正處在測試階段(我使用的是 Burton Beta 1 刷新位版本 40607.83),并且在該產品發布之前,可能會對 UI 或某些特定步驟進行更改。在對 EPT 進行介紹之前,我希望花點兒時間談論一下分析器通常是如何工作的,以便您可以更好地了解是什么使 Enterprise Performance Tool 變得如此與眾不同。
分析器的基本原理
在您編寫分析器時,可以選擇兩種收集數據的方式中的一種:探測和采樣。這兩種方式都十分有效,但是每種方式都有它的折衷方案。探測分析器收集數據的方式是在應用程序中插入探測或掛鉤,以便在程序執行該掛鉤時就調用分析器運行庫。要放置探測,分析器需要在編譯步驟中將應用程序儀表化,重寫已經編譯的二進制文件,或者即時將應用程序儀表化。要查看基于 .NET 的應用程序的探測分析器方法示例,請閱讀 Aleksandr Mikunov 的一篇非常出色的文章 —“Rewrite MSIL Code On the Fly with the .NET Framework Profiling API”(該文章摘自 MSDN?Magazine 2003 年 9 月刊)。當我開始討論 EPT 的時候,您將看到它使用術語“儀表化”來表示探測方法。
探測分析器方法的主要優勢在于,當應用程序執行時,將始終調用所插入的探測。這樣,分析器運行庫將對運行具有完整的認識,因此在生成關鍵信息(例如,函數之間的父子關系)時可以確保正確,并且分析器可以報告完美的調用樹,以便您可以輕松找到花費最長時間的調用路徑。使用探測分析器時,沒有什么事情能夠阻止開發人員只在函數入口和出口處插入探測??梢栽谠创a行級別放置額外的探測,以便您對函數具有完整的認識。
但是,探測分析器所提供的詳細視圖具有一些缺點。第一個缺點是儀表化方案使用起來可能很麻煩,并且因為它是在二進制級別重寫,因此存在很多可能引入潛在錯誤的領域。正如您可以想像到的那樣,這些探測還占用了空間,從而導致一些代碼膨脹和較低的性能。對于完全儀表化的應用程序,探測分析器可能會導致速度大幅度下降,以至于幾乎不可能在生產系統上運行儀表化的二進制文件,從而使您在最需要該分析器的時候卻無法利用它。
正如其名稱所暗示的那樣,采樣分析器按照預先定義的時間間隔獲得應用程序中正在執行的操作的快照。大多數開發人員都沒有意識到 Microsoft 總是在他們的開發環境中隨附了一個采樣分析器。它被稱為調試器! 如果您開始調試應用程序,并且每隔 30 秒左右就中斷至調試器,則您可以注意到應用程序線程正在何處執行,以便很好地了解應用程序在一次運行過程中執行了哪些操作。我已經通過手動完成采樣分析器的工作,解決了很多生產性能問題。
使采樣分析器如此有價值的原因在于,它們具有比探測分析器小得多的系統開銷。這意味著,您可以有更高的機會在生產系統中使用它們,而不會使服務器疲于奔命以至于停機。采樣分析器的問題在于,從應用程序中獲得的所有樣本很有可能根本不顯示任何代碼。例如,如果您具有大量使用數據庫的應用程序,則所有樣本都可以來自數據庫訪問程序集的內部。最后,只抓取每個線程的當前執行指令的傳統采樣分析器會使得確定方法之間的父子關系變得十分困難,因而確定性能最差的執行代碼途徑要困難得多。
Enterprise Performance Tool 的基本原理
在了解分析器的操作方式之后,我就可以討論 EPT 所采取的方式了。簡單地說:它既是采樣分析器,又是探測分析器(Microsoft 稱之為“儀表化”)。其思想是,您在開始時將通過采樣分析器來查看應用程序性能,以獲得常規性能特征,以便您可以開始將注意力集中于應用程序的熱點問題上。在您了解具有一些問題的程序集之后,就可以求助于儀表化分析以查看特定的問題領域,以便修復它們。當然,如果您要執行單元性能測試,則沒有什么能夠阻止您直接轉到對特定模塊進行儀表化,以便在聚焦方案中查看它們的性能。
使 EPT 采樣分析器有趣的部分原因在于,您可以使用大量項目來觸發樣本。默認的采樣點是時鐘周期,并且可能是您總是使用的采樣點。默認情況下,每一百萬個時鐘周期采樣一次,但是您可以將采樣間隔的時鐘周期數更改為您喜歡的任何值,可是該值越小,EPT 所導致的系統開銷就越大。對于生產服務器,您可以將該數字設置為某個非常高的數字(如五百萬),以使系統開銷保持在合理的水平,同時不會完全破壞進程中的可用性。正如您預料的那樣,每五百萬個時鐘周期采樣一次將意味著您需要使應用程序運行相當長的時間,以便在您的熱點區域中獲得良好的樣本分布。
如果您的應用程序使用了很多內存,則可以選擇讓 EPT 采樣分析器改為在出現頁錯誤時觸發。這樣,您就可以在數據被交換出 RAM 時獲得性能快照,并且可以看到是誰在執行推送操作。如果初始分析器運行表明您在代碼外部的區域中花費了大量時間,則可以告訴分析器改為基于系統調用來完成采樣。如果您要分析具有大量線程的多線程應用程序,則該采樣統計信息會對您在從用戶模式轉換到內核模式(這表明某些線程可能會不必要地在內核對象上阻塞)時的數據進行拍照。您可以用于采樣觸發器的最后一些值是 CPU 所支持的各種性能計數器,例如,分支計數或緩存丟失。這是一個只有極少數人才確實需要的高級選項,但是如果您確實需要該數據,那么知道該數據存在也不錯。
那些忙碌的 Redmontonian 還解決了調用堆棧問題 — 這是對有用的采樣分析器造成障礙的最大問題之一。正如我在前面提到的那樣,大多數采樣分析器在采樣時只是對當前正在執行的指令進行拍照。Microsoft 解決了如何將極快的堆棧遍歷結合到他們的采樣分析器部分中,以便您能夠獲得樣本的好處,并且知道在執行該樣本時是如何到達那里的。這使得將這些快照與代碼重新關聯變得更加容易。
在討論您可以分析的應用程序之前,我想提幾件您很可能覺得有趣的事情。第一件事情是,如果您認為 Microsoft 是從頭開發該性能工具的,那么您只猜對了一半。在 Microsoft 內部,開發團隊一直在使用 EPT 的前身(名為 Call Attribute Profiler (CAP),它使用儀表化)和 Low Overhead Profiler (LOP) — 一個采樣分析器。由于 Microsoft 開發了這些工具以收集有關應用程序(例如,操作系統和整個 Office 套件)的性能信息,因此它們甚至不會給您的應用程序帶來什么負擔。我曾經使用過 EPT 的前身,所以我可以告訴您公共版本使用起來會容易多少。此外,它們還具有一些極為有趣的功能(稍后我將予以討論)。
第二個有趣的事項與 EPT 所支持的技術有關。盡管某些人可能認為由于 Microsoft 非常偏重于 .NET Framework,因此無法將 EPT 用于 Win32 應用程序或本機代碼,但 EPT 團隊實際上已經承諾支持所有的 Win32 本機應用程序以及 .NET 代碼。這意味著,無論您使用哪種技術(ASP.NET、Windows? 窗體、MFC 或 Win32 服務),您都具有完全的采樣和儀表化支持。您將看到,在 Visual Studio .NET 中,跨技術使用 EPT 沒有任何差異。
實際的 EPT 設置非常平常;只需從 Visual Studio .NET 安裝程序的“Enterprise Tools”樹控件中選擇“Enterprise Performance Tool”即可。當然,因為您知道 EPT 仍然是一個測試產品,所以您的第一個反應可能是運行虛擬 PC,并在那里安全地包含所有內容。但是,為了執行采樣分析,EPT 使用內核模式設備驅動程序來響應 CPU 性能計數器中斷,不過令人遺憾的是,虛擬 PC 沒有實現計數器。它也沒有模擬高級可編程中斷控制器 (APIC),而這兩者都是內核設備驅動程序完成其工作所必需的。好消息是,如果您沒有額外的計算機以便安裝 EPT,那么您也并非完全不幸,因為儀表分析器仍然能夠工作。如果您沒有多余的計算機以便安裝 EPT,那么這是一個讓公司為您購買另一臺計算機的好借口。
Animated Algorithm
要學習任何工具的用法,您都需要一個合適的示例應用程序,以便能夠最佳地利用該工具。在測試周期的這一時刻,EPT 沒有隨附任何示例,但是在我的硬盤上已經有了一個完美的分析器示例。早些時候,我正在嘗試解決如何在 Windows 窗體應用程序中使用多線程的問題,因此我編寫了一個名為 Animated Algorithm 的了不起的小程序,該程序可實時激活大量排序算法。圖 1 顯示我的示例應用程序已經準備好排序。

圖 1 正在工作的 Animated Algorithm
Animated Algorithm 使您可以在窗體的組合框中,從 15 個不同的排序算法中進行選擇?!癘ptions”菜單使您可以選擇各個元素交換或設置之間的休眠時間,以便您可以降低圖形更新的速度。
我不久前使用 Microsoft? .NET Framework 版本 1.1 編寫了 Animated Algorithm,因此您不會在代碼中找到任何奇特的泛型或新的 BackgroundWorker 項。NSORT 程序集中的排序算法來自由 Jonathan de Halleux、Marc Clifton 和 Robert Rohde 張貼到 The Code Project 上的一篇優秀文章(請參閱 Sorting Algorithms In C#),該程序集將算法封裝到公共結構中,以便您可以輕松地替換執行元素交換和設置的類。因為它們具有非常好的體系結構,所以我需要關心的所有內容為 UI 部分。
在本文的其余部分中,我將分析 Animated Algorithm 程序。如果 EPT 團隊將該程序作為示例應用程序隨附在產品中,則會非常棒。(哈哈。)
EPT 入門
在 Visual Studio 2005 Beta 1 中,在哪里可以找到 EPT 當然是不明顯的。EPT 在您啟動 Performance Wizard(它位于“Tools”菜單下)時啟動,并且無論是否打開項目,它都存在。請記住,Performance Wizard 所創建的性能會話不是項目的一部分;它們實際上是具有自己的 IDE 窗口(稱為 Performance Explorer)的單獨文件。您可以通過從“File”|“Open”對話框中選擇 PSESS 文件,來打開您創建的性能會話。
如果您在單步執行 Performance Wizard 時沒有打開項目,則所產生的性能會話將與您指定的二進制文件相關聯。但是,在測試版中,在您指定要運行的二進制文件時,必須打開關聯的項目。我只是想順便提一下這個小小的技巧,因為當我第一次遇到該問題時,它確實讓我困惑不已。
在您啟動 Performance Wizard 以后,呈現在您面前的第一個屏幕要求您選擇要分析的應用程序。如果您打開了一個可生成多個程序集的項目(如 Animated Algorithm),則只能從該向導中選取一個程序集。如果要進行采樣,則只選取這一個程序集是很好的,因為 EPT 采樣會分析加載的所有程序集(包括那些來自框架類庫的程序集)。但是,如果您要對多個程序集執行儀表化分析,則 Performance Wizard 只選擇這一個程序集,因此您將需要在 Performance Explorer 中所生成的性能會話中指定其他項目或程序集。稍后我將向您說明如何完成該工作。
在選擇了要在性能會話中使用的程序集或項目之后,您必須選取分析方法。在 Performance Explorer 中的任何位置,您都可以在采樣和儀表化之間切換,以滿足自己的需要;您在該向導頁中進行的選擇只表示您最初希望執行的操作。在選擇了分析方法之后,向導就基本完成了。對于 EPT 的最終版本,您將在 Performance Wizard 中具有用于指定附加信息的更多選項。最終版本還將使您可以直接從 Performance Explorer 中創建性能會話。
圖 2 顯示了 Performance Explorer 在剛剛完成 Performance Wizard 步驟以創建 AnimatedAlgorithms 項目的儀表化運行之后的窗口。要添加另一個項目的輸出二進制文件,請右鍵單擊“Targets”文件夾,然后從上下文菜單中選擇“Add Target Project”。如果要添加與該項目沒有關聯的特定二進制文件,請選擇另一個選項 —“Add Target Binary”。如果您已經選擇了“Add Target Project”,則可以在產生的對話框中從已打開的解決方案中選擇其他項目。

圖 2 Performance Explorer
如果您已經選擇了儀表化運行(它由綠色啟動箭頭下面的下拉列表框中的文本表示),則二進制文件儀表化將在程序執行之前發生。如果您不希望針對運行儀表化某個特定的二進制文件,則請右鍵單擊該二進制文件,并取消選中“Instrument Binary”菜單選項。
如果您已經選擇了采樣分析,并且希望附加到某個正在運行的項目,則單擊“Attach/Detach”按鈕(“Start”按鈕右側的斜向箭頭)將呈現“Attach Profiler to Process”對話框。通過 EPT,您可以根據需要附加到任意多的進程,以便獲得對應用程序的認識。“Attach Profiler to Process”對話框還允許您從特定的二進制文件中分離分析。在將來的某一期 MSDN Magazine 中,我將更詳細地討論如何附加到現有的進程(特別是為了進行 ASP.NET 性能調整)。
Performance Explorer 窗口頂部的最后一個按鈕是無所不在的“Properties”按鈕。在啟動分析運行之前,您可能希望瀏覽一下性能會話屬性,以設置幾個關鍵屬性。第一個屬性位于“General”選項卡上,它是您希望為性能會話存儲性能報告的位置。在分析項目時,默認設置是將報告存儲在與解決方案相同的目錄中。但更好的做法是將性能會話和它們的相應報告放置在它們自己的目錄中,以便您可以更容易地存儲特定的運行集。這樣還可以更容易地分析之前和之后的情況,以便查看您所進行的代碼更改的影響。
在“General”選項卡上,您還可以在儀表化和采樣分析之間切換(這會更改在 Performance Explorer 中顯示的值)。在我進行的性能調整中,我喜歡將特定的會話專用于單個類型的分析,以避免出現與報告有關的混淆。沒有任何事情阻止您為所有種類的特定方案(涵蓋從分析類型到單個二進制文件儀表化的所有方案)創建數以百計的不同性能會話文件。我還將提一下“General”選項卡上的最后一個項,它具有一個非常誘人的名稱 —“Managed Allocation Profiling”,相信這會使您感到更加好奇。在我討論完常規分析之后,我將返回到該項。
“Performance Session”屬性頁上的另一個有趣的選項卡是“Sampling”選項卡(請參見圖 3)。在這里,您可以告訴 EPT 您要執行哪種類型的采樣。正如我在前面提到的那樣,您對于希望如何進行采樣具有非常好的控制。

圖 3 各種 EPT 采樣計數器選項
在執行分析運行時,EPT 會在二進制文件在硬盤中所處的位置上將其儀表化。如果您希望將儀表化的二進制文件移動到另一個位置,請選擇“Performance Session”屬性頁中的“Binary”選項卡,然后選中“Relocate Instrumented Binaries”(它與 REBASE 樣式的重定位絕對沒有任何關系),并且指定您希望將更改后的二進制文件移至何處。
“Instrumentation”選項卡使您可以指定希望在儀表化發生之前和之后運行的程序。如果您需要對儀表化的二進制文件執行其他任務(例如,將其移動到全局程序集緩存中或 Web 服務器上的特定位置),則該選項卡可能很有用?!癆dvanced”選項卡在該測試版中未公開。最后,通過“Counters”選項卡,您可以告訴 EPT 從系統的 CPU 中收集其他數據,例如,L2 或 L3 緩存讀取不中。顯然,這些選項是只有少數開發人員才會需要的非常高級的選項,但是如果您確實需要它們,那么它們可以發揮巨大的作用。
在我繼續討論查看采樣數據之前,我想提一下,“Performance Explorer”窗口可以根據您的需要打開任意多個性能會話。當您希望觀察特定的前后方案,或者希望用不同的儀表化二進制文件執行單獨的測試運行時,這一點極為有用。當您打開多個性能會話時,應當確保右鍵單擊特定的會話,選擇“Set as Current Session”以便讓該會話的設置執行,然后將報告歸檔到它的報告節點中。
查看分析器數據
將性能會話設置為您希望執行的操作以后,就可以啟動分析了。我將首先對 Animated Algorithm 執行采樣分析,以查看我是否可以找到一些熱點。從采樣中獲得良好數據的關鍵在于執行較長時間的運行。對于 Animated Algorithm,我會將 15 個排序算法中的每一個算法運行兩次,并將采樣設置為默認的一百萬個時鐘周期。
在完成某個運行之后,EPT 會將該運行的報告放到性能會話的“Reports”文件夾中。EPT 在運行期間收集原始性能數據,并將其流式傳輸到報告文件中(不做任何分析)。這樣,您可以在運行應用程序時避免所有系統開銷,但是您將為大型報告文件付出代價。我剛才完成的運行的采樣報告文件大小為 3.70MB,它用了大約三分鐘才完成。請確保您在運行 EPT 時具有大量的磁盤空間。
所有數據分析(它必然伴有調用堆棧的生成以及性能數字的計算)都在您打開報告文件時發生。對于測試版,在打開文件時速度可能會降低??雌饋硪晥D好像處于無限循環中,但是,如果進度欄正在報告窗口中移動,那么請您耐心一些,文件最終將彈出。
任何分析運行中的第一個視圖是“Performance Report Summary”,它顯示在剛剛完成的 Animated Algorithm 采樣運行的圖 4 中。不出所料,采樣將發生在整個應用程序中,因此您正在查看的信息也就是您將在應用程序中看到的內容:大部分工作都發生在框架類庫或操作系統內部。如果您確實在采樣“Summary”視圖中看到了您的一個方法,則您很可能看到了一個性能問題。

圖 4 EPT 采樣性能報告摘要
快速瀏覽一下圖 4,您可能想知道 Inclusive Sampled 和 Exclusive Sampled 之間的區別。Exclusive Sampled 意味著該方法在取樣時位于堆棧的頂部。換句話說,它是當前正在執行的函數。Inclusive Sampled 意味著該函數在取樣時出現在調用堆棧中。因而,包含方法是當前正在執行的方法的調用方。
在采樣方案中,一個方法在調用堆棧 (Inclusive Sampled) 中出現的次數越多,該函數在執行中花費的時間就越多,因此這里是您需要重點關注以進行性能調整的地方。對于 Exclusive Sampled 函數而言,函數在那里頻繁出現表明該函數正在被頻繁地調用,但是它的執行實際上可能非??焖?。對于像 Animated Algorithm 這樣需要進行大量圖形處理的應用程序,我完全能夠預料到 GDIPLUS.DLL 中的某個函數將靠近剛剛顯示的列表的頂部。在圖 4 中,位于 GDIPLUS.DLL 中偏移量 0x5B8D 處的函數(它恰好是 FLOOR 函數)被一直調用,以便計算在屏幕上的哪個位置顯示某些內容。當您觀察性能運行時,請確保設置符號服務器以獲得可能存在的最佳信息。在撰寫本文時,我使用了 EPT 的未發布版本,因而符號尚不可用。
在我跳到其他視圖中以前,我希望儀表化 Animated Algorithm,并且完成與我針對采樣分析器完成的運行相同的運行,以便顯示儀表化運行的性能報告摘要。正如您可以猜到的那樣,儀表化的運行會生成比采樣運行多得多的數據。對于該運行,我儀表化了 Animated Algorithm 中的全部五個程序集,并最終得到一個 375MB 大小的會話文件。
采樣和儀表化數據之間的主要區別是:采樣查看整個進程空間,并且將顯示框架類庫或操作系統內部(換句話說,就是您在其中不具有源代碼的位置)的調用。另一方面,儀表化只查看應用程序以及您在非儀表化模塊上直接調用的方法。例如,如果您具有一個“Hello World!”應用程序,并且它的 Main 只調用 Console.WriteLine,則您將獲得 Main 中任何工作的計時信息以及 Console.WriteLine 長度的計時信息,但是您不會獲得有關 Console.WriteLine 方法的任何詳細信息。
圖 5 顯示了儀表化運行的性能報告摘要。第一個表“Most Called Functions”顯示了頻繁使用的函數。該表中的第一列被錯誤標記為時間;它實際上表示對該函數的調用次數。百分比列顯示了對該特定函數進行的調用總次數所占的百分比。在大多數運行中,您將在這里看到框架類庫或操作系統函數。如果您看到一些來自您自己的代碼的函數,則您最好了解一下您為什么如此頻繁地調用該特定函數。

圖 5 儀表化運行的摘要
“Functions with Most Individual Work”表列出了那些花費大部分時間以僅僅執行該函數(沒有任何其他函數調用)的方法。這也稱為該函數的獨占時間。對于測試版本,“Time”列的單位為時鐘走格數。對于最終版本,單位將是毫秒。但是,我認為性能運行的實際原始單位對于分析沒有用。最重要的數字是百分比。在觀察性能問題時,您希望知道,與應用程序中的所有其他方法相比,哪個方法占用了最長的時間。您在觀察像 3519639455 和 3492589504 這樣的兩個數字時,很難對它們進行什么比較。幸運的是,該表包含百分比,而我對 EPT 團隊的建議是從圖表中丟棄原始數據。
最后一個表“Functions Taking Longest”顯示方法的實際時間(也稱為跑表時間或運行時間)。分析器記錄方法的入口點時間和出口點時間,并將這兩個值相減。該數字涵蓋了被調用的所有子方法、所有上下文切換以及該方法執行的休眠。在圖 5 中,您可以看到 System.Windows.Forms.Application.Run 占用了最長時間,就像您對 Windows 窗體應用程序所預料的那樣。盡管很多開發人員將注意力集中于獨占時間,但這只是整個性能狀況的一小部分。如果方法正在對數據庫進行調用或者進行 Web 服務調用,則您的方法在運行時所在的線程將在等待這些調用返回數據時阻塞,從而使得該線程從 CPU 中被移走。通過密切關注方法的運行時間,您可以找到代碼中正在降低應用程序運行速度的部分。
盡管摘要視圖很不錯,但您最感興趣的將是查看代碼在何處阻塞了系統的其余部分(對于采樣運行而言),或者阻塞了應用程序的其他方法(對于儀表化運行而言)。這是“Function”視圖的職責范圍 — 通過單擊報告窗口底部的“Function”按鈕可以選擇該視圖。您還可以雙擊“Summary”視圖的任何方法以跳至“Function”視圖。
對于采樣運行,“Function”視圖顯示了至少一個包含捕獲中所有函數捕獲的列表。對于儀表化運行,您將看到作為該運行的一部分調用的所有儀表化方法。無論您正在執行哪種類型的分析,都會在“Function”視圖中顯示很多數據,因此您可以對代碼的狀況有一點兒感覺。
默認情況下,采樣“Function”視圖顯示“Inclusive Samples”列和“Exclusive Samples”列。由于我喜歡百分比數字,因此我右鍵單擊了列標題以向列標題中添加“Inclusive Percent”和“Exclusive Percent”。如果您要對多進程系統進行采樣,則可能希望包含其他列(例如,“Process Name”或“Process ID”),以便您可以標識哪個方法采樣與哪個進程相配。您還可以在儀表化“Function”視圖中設置列標題,但是您將具有不同的標題組以供選擇。
在“Function”視圖中分析采樣運行時,我喜歡首先掃一眼“Function”視圖的頭幾個按“Inclusive Samples”列排序的頁,以了解正在執行的方法。如果我在頭幾個頁中沒有看到我的任何方法,則我會右鍵單擊“Function”視圖并選擇“Group by Module”,以便獲得樹報告視圖。當您將函數按模塊分組時,按特定列排序可以正確執行 — 這是一項很不錯的功能。
對于儀表化運行,“Function”視圖具有更多要顯示的列。如果您擁有一臺 40 英寸的顯示器,則無需最大化 Visual Studio .NET 窗口就應當能夠看到所有這些列。對于我們中的其他人而言,查看“Function”視圖的最佳方式是按 Alt + Shift + Enter 以切換到全屏幕模式。
在這些列中,“Function”視圖中的儀表化運行使用我在前面解釋過的“包含”和“獨占”術語。但是,還有另一個使人混淆的術語:應用程序。正如我提到的那樣,運行時間是從一個儀表化點到另一個儀表化點的總時間,而不管該線程可能進行了哪些上下文切換。應用程序時間的思想是 EPT 將提取出在這些上下文切換中所花費的時間,以便您可以看到您的代碼在 CPU 中實際執行的時間。圖 6 列出了您將在儀表化“Function”視圖中看到的不那么明顯的列的定義。您可能希望將它傳送到顯示器上,直到 EPT 的聯機幫助問世。
在觀察儀表化運行的“Function”視圖時,我添加了這些列以查看各種計時的百分比值,移除原始數字時間列,并且添加了兩個轉換列。這為我提供了有關該運行的更清晰視圖。我在排序時所依據的第一個列是“% Application Exclusive Time”,因為我希望看到哪個函數正在完成大部分工作。由于儀表化在方法進行的所有子調用周圍放入了探測,所以您完全有可能在該列表的頂部看到框架類庫或操作系統。實際上,對于我的 Animated Algorithm 運行,System.Drawing.SolidBrush.ctor 和 System.Drawing.Brush.Dispose 在 Application Exclusive Time 百分比中被列為第一和第二,其百分比分別為 14.982% 和 14.867%。我編寫的第一個函數是位于第三位的 Bugslayer.SortDisplayGraph.SorterGraph.UpdateSingleFixedElement(其百分比為 12.217%),它在圖形中繪制單獨的條。根據應用程序類型的不同,我在查看“Function”視圖時可能會選擇按其他列排序。如果存在 Web 服務或數據庫調用,則我將查看 % Elapsed Inclusive Time,以便可以看到是否有特定方法卷入到長時間阻塞中。對于像 Animated Algorithm 這樣的應用程序,我還將查看 Application Inclusive Time 的百分比。
基于我的儀表化運行中的上述數字,我很想查明是誰在對 SolidBrush 方法進行這些調用,因此我右鍵單擊 .ctor 方法并選擇“Show in Caller/Callee”視圖,以便查看是誰在調用該方法。該視圖(它對于采樣分析也可用)使您一眼就可以看出目標方法的所有調用方,以及該目標方法調用的所有方法。
因為 .ctor 方法沒有儀表化,所以“Caller/Callee”視圖將不會顯示任何被調用方,但是它顯然會顯示調用方。我雙擊了這個唯一的調用方,它恰好是具有第三高 Application Exclusive Time 并具有圖 7 所示視圖的 UpdateSingleFixedElement 方法。
在圖 7 中,位于視圖中部的下拉組合框是目標方法(在本例中為 UpdateSingleFixedElement)。方法上方的網格包含了目標方法的所有調用方(調用方)。目標方法下方的網格包含了目標方法調用以完成其工作的所有方法(被調用方)。如果您希望查看是誰調用了特定調用方,請雙擊該調用方方法,該方法將變為目標方法,并且您將看到原始目標方法下降到被調用方部分中。實質上,您只是將堆棧遍歷了一遍。
僅僅基于圖 7 中的視圖,您就可以辨別出潛在的性能問題。Animated Algorithm 似乎不具有任何突出的性能問題,但是 SolidBrush .ctor 和 Dispose 占用了如此多的時間并且都在 UpdateSingleFixedElement 方法內部調用(調用了 351,872 次),這個事實表明我做了一件愚蠢的事情 — 我每次都通過該函數創建畫筆,而實際上應該將其緩存。當我在將來的某一期 MSDN Magazine 中開始用 EPT 分析代碼時,您還將看到 Animated Algorithm 的其他一些問題。
數據的最后一個常用視圖是“Callstack”視圖。在這里,您可以通過更具層次性的方式看到您在“Caller/Callee”窗口中觀察到的調用堆棧。對于采樣運行,您將在“Callstack”視圖的頂層看到很多的條目,因為這些條目中的每一個都代表一個包含獨占樣本的唯一點。當您在采樣運行中展開項時,您還將看到,在相同級別偶爾會存在一些項,這些項指示位于根部的函數具有多個引向它的調用樹。根位置中顯示的項是棧頂。
對于儀表化運行,“Callstack”窗口將具有與應用程序中的每個線程相對應的根元素。因為 Animated Algorithm 只有兩個線程,所以您只能在樹根級別看到兩個項。在“Callstack”視圖中,您可以看到絕對調用堆棧(從儀表化的第一個方法向下到最后一個方法),因此您可以真正了解應用程序的執行方式。我已經有很多次對我認為代碼所完成的工作和代碼實際上完成的工作之間的差異感到吃驚。
您可以花費大量時間在“Callstack”窗口中分析代碼。當通過應用程序觀察特定的蹤跡時,您可以通過選擇感興趣的特定節點,向下移動,右鍵單擊,并選擇“Set Root”菜單選項,來消除大量噪音。在圖 8 中,我希望查看 NSort.SwapSorter.Sort 進行的所有調用,因此將它設置為根可以消除 UI 線程的影響。
在將來的某一期中,我將更詳細地討論 EPT 顯示區域中的最后兩個選項卡:“Trace”和“Type”。在“Type”視圖中,您可以觀察已經在應用程序中分配的對象。它在測試版中有效。當我在前面討論性能會話屬性時,我提到過在“General”選項卡上有一個“Managed Allocation Profiling”部分。如果您選擇“Allocations-only”單選按鈕,則 EPT 會填充“Type”視圖。在測試版中,報告看起來類似于其他許多工具中的報告,但是數據收集似乎不像在其他工具中那樣具有如此之多的系統開銷。最后,要了解 Enterprise Performance Tool 團隊的想法以及有關該工具的更多信息,請確保在 blogs.msdn.com/profiler 查看他們的網絡日記。
John Robbins 是 Wintellect 的創始人之一,該公司是一家專門致力于 Windows 和 .NET Framework 的軟件咨詢、教育和開發公司。他的最新著作是“Debugging Applications for Microsoft .NET and Microsoft Windows”(Microsoft Press, 2003)。要聯系 John,請訪問 www.wintellect.com。