使用 Visual Studio 分析器找出應用程式瓶頸

來源:互聯網
上載者:User
在過去十年間,湧現了許多新的軟體技術和平台。每種新技術都要求掌握專門的知識才能建立出效能良好的應用程式。現在,由於各種 Internet 技術(如部落格)使失望的使用者可輕鬆地否定您的應用程式,因此您確實需要將效能放到首要位置。在計劃早期,就應添加響應效能要求並建立原型來確定可能的技術限制。在整個開發過程中,還應衡量應用程式的各個效能方面以發現可能的效能下降,同時確保速度較慢情形下的測試人員檔案並跟蹤其錯誤。即使擁有最好的計劃,仍必須在產品開發過程中調查效能問題。在本文中,我們將向您展示如何使用 Visual Studio Team System Development Edition 或 Visual Studio Team Suite 來確定應用程式中的效能瓶頸。將通過演練一個樣本效能調查來向您介紹 Visual Studio 分析器。請注意,儘管我們在本文中是使用 C# 來編寫程式碼範例,但是此處的大部分樣本對於本機 C/C++ 和 Visual Basic 代碼也同樣有效。

應用程式分析我們將使用先前提及的兩個 Visual Studio 版本所附帶的分析器。首先編寫一個用於繪製 Mandelbrot 不規則圖形的小型樣本項目(如圖 1 所示)。該應用程式不是非常有效,並且需要約 10 秒鐘才能繪製出不規則圖形。Figure 1 效能測試的目標程式 (單擊該映像獲得較大視圖)要開始調查,從 Visual Studio 2008 的新“Analyze”(分析)菜單啟動“Performance Wizard”(效能嚮導)。在 Visual Studio 2005 中,此功能可從“工具”|“效能工具”菜單獲得。從而啟動一個包含三個步驟的嚮導,其中第一步是指定目標項目或網站。第二步提供兩種不同的分析方法:採樣和檢測。(有關這些分析方法的詳細資料,請參閱“效能分析解釋”側欄。)現在,我們將選取預設值。嚮導完成後,顯示一個“Performance Explorer”(效能資源管理員)對話方塊並建立一個新的效能會話。此會話包含目標應用程式(在我們的樣本中為 Mandel)並且沒有報告。要啟動分析,單擊工具視窗工具列中的“Launch with Profiling”(啟動並分析)按鈕。應用程式繪製完不規則圖形後,立即關閉表單停止分析。Visual Studio 自動將一個新建立的報告添加到效能會話中並開始進行分析。分析完成後,Visual Studio 分析器會顯示“Performance Report Summary”(效能報告摘要),列出開銷最大的函數(請參見 圖 2)。報告以兩種方式顯示這些函數。第一種方式衡量所列出函數直接或間接執行的工作。對於每個函數,數字代表在函數主體及其所有子調用中收集的積累樣本。第二個列表不計算在子調用中收集的樣本。此摘要頁面顯示 Visual Studio 分析器在執行 DrawMandel 方法期間收集了 30.71% 的樣本。剩餘 69% 的樣本則分散在其他各個函數間,在此就不加贅述。要瞭解更多有關報告選項的資訊,請參閱側欄“報告可視化選項”。Figure 2 效能測試顯示開銷較大的函數調用 (單擊該映像獲得較大視圖)請查看報告的“Call Tree”(調用樹)視圖(如圖 3 所示),“Inclusive Samples %”(包含樣本 %)列代表在函數及其子項中收集的樣本。“Exclusive Samples %”(獨佔樣本 %)列代表僅在函數主體中收集的樣本。可看到 DrawMandel 方法直接調用 Bitmap.SetPixel。儘管 DrawMandel 自身佔據了總樣本的 30.71%,但 Visual Studio 分析器從 Bitmap.SetPixel 及其子項收集了 64.54% 的樣本。其中 Bitmap.SetPixel 主體僅占 0.68%(因此它並未顯示在摘要頁面上)。但是,Bitmap.SetPixel 通過其子項產生了大部分處理。它才是應用程式的真正瓶頸。Figure 3 被測應用程式的調用樹樣本 (單擊該映像獲得較大視圖)顯然地,Bitmap.SetPixel 對於 Mandel 項目而言並非最佳。我們的應用程式需要一種更快的方式來訪問表單上的所有像素。幸運的是,位元影像類還提供有另一個有用的 API:Bitmap.LockBits。此函數允許程式直接寫入位元影像記憶體,從而減少了設定單個像素的開銷。此外,為最佳化繪圖,我們將建立一個純整數數組並用每個像素的顏色值加以填充。隨後,通過單個操作將該數組的值複製到位元影像中。

最佳化應用程式效能分析解釋使用採樣方法 進行分析時,分析器以一種類似於偵錯工具的方式附加到正在啟動並執行進程。然後,分析器會定期中斷進程並檢查哪個函數處於堆棧頂部以及該函數的代碼路徑。換句話說,Visual Studio 分析器收集當前進程狀態的樣本。採樣是一種非入侵式統計型分析方法。在函數中收集的樣本越多,函數可能執行的處理就越多。Visual Studio 分析器還會收集有關導致此執行的調用路徑的資訊。因此,此工具可在分析收集的資料後顯示整個呼叫堆疊。預設情況下,Visual Studio 分析器每 1 千萬個 CPU 週期收集一個樣本。除 CPU 週期外,還可能在出現其他事件(如分頁錯誤、系統調用、CPU 快取缺失等等)時執行採樣。分析會話的屬性控制分析器的取樣對象以及頻率。作為一個低開銷解決方案,採樣常常是推薦選項。但值得注意的是,採樣僅在程式有效使用 CPU 時收集資訊。因此,當進程在等待磁碟、網路或任意其他資源時,Visual Studio 分析器均不會收集樣本。這就是如果應用程式並未有效使用 CPU,建議使用檢測分析的原因。在檢測模式中,Visual Studio 分析器通過在每個函數的開頭和結尾處注入特殊指令(稱為探針)來修改(檢測)二進位檔案。探針允許分析器度量運行每個函數所花的時間。此外,分析器還會在每個外部函數調用周圍添加一對探針,從而可確定這些外部調用的開銷。通過使用檢測分析,可準確測量各種資料,如運行函數所花時間(“經過的時間”)、函數的調用次數以及函數正在使用 CPU(“應用時間”)且未被 OS 切換出來的時間。檢測的缺點是收集了大量資料,因而需要花費更長的分析時間。此外,此分析模式還具有更高的運行時開銷。更高開銷可能不經意間更改所分析應用程式的效能特徵。通過同時使用採樣和檢測,還可收集基於 Microsoft .NET Framework 的應用程式的記憶體配置資料。使用者可使用效能會話屬性頁面啟用和調整 .NET 記憶體配置資料的收集。它通常被稱為記憶體分析,並且有大量關於該主題的 MSDN 文檔。請注意,它是分析器中唯一一個僅用於 .NET Framework 相容代碼的功能。對於其他功能,Visual Studio 分析器在本機 C/C++ 和基於 .NET 的應用程式之間完全相同。

接下來修改 DrawMandel 方法以使用 LockBits 而非 SetPixel,並看看此更改會產生何種效能。建立位元影像後,添加以下程式碼來鎖定位元影像位並獲得指向位元影像記憶體的指標:

複製代碼

BitmapData bmpData =     bitmap.LockBits(        new Rectangle(0, 0, Width, Height),         ImageLockMode.ReadWrite,         bitmap.PixelFormat);IntPtr ptr = bmpData.Scan0;int pixels = bitmap.Width * bitmap.Height;Int32[] rgbValues = new Int32[pixels];

然後,在設定像素的內部迴圈中,注釋掉對 Bitmap.SetPixel 的調用並用新語句加以替換,具體如下:

複製代碼

//bitmap.SetPixel(column, row, colors[color]);rgbValues[row * Width + column] =     colors[color].ToArgb();

此外,添加以下程式碼來將數組複製到位元影像記憶體中:

複製代碼

Marshal.Copy(rgbValues, 0, ptr, pixels);bitmap.UnlockBits(bmpData);

現在,如果重新在分析器中運行應用程式,可以看到不規則圖形的繪製速度幾乎快了三倍(請參見圖 4)。請注意,新效能報告的摘要頁面顯示 DrawMandel 的主體直接佔據了總樣本的 83.66%。由於我們最佳化了繪圖,瓶頸現在變成了不規則圖形的計算。Figure 4 修訂代碼的效能分析 (單擊該映像獲得較大視圖)現在,我們將更進一步最佳化該計算。遺憾的是,此次需要尋找單個函數中的瓶頸。DrawMandel 是一個比較複雜的方法,因而很難知道應關注哪些計算。幸運的是,Visual Studio 2008 採樣分析器還預設收集行級資料,從而有助於確定函數中的哪些行開銷最大。要查看行級資料,需從其他角度查看效能報告。從“Current View”(當前視圖)菜單切換到“Modules”(模組)視圖。與“Call Tree”(調用樹)視圖不同,“Modules”(模組)視圖不會顯示在父函數上下文中各函數的相互調用方式以及這些調用的開銷等資訊。相反,“Modules”(模組)視圖包含每個可執行檔(程式集或 DLL)以及該可執行檔中每個函數的累積總樣本數。Visual Studio 分析器從所有呼叫堆疊累積該資料。“Modules”(模組)視圖比較適合於觀察更大的圖片。例如,如果按“Exclusive Samples %”(獨佔樣本 %)列排序,可以看到 Mandel.exe 自身執行 87.57% 的處理。作為最佳化後的結果,GDI+ 佔用不到 3% 的處理。展開這些模組,可以看到單個方法的相同資訊。此外,在 Visual Studio 2008 中,除函數級以外,還可展開樹來查看單個行甚至這些行中單個指令的相同資料(請參見圖 5)。Figure 5 跳到分析的程式碼 (單擊該映像獲得較大視圖)跳到原始碼可查看如圖 6 所示的代碼。代碼在最內部迴圈中計算平方根。此操作開銷很大且佔用 18% 的總應用程式處理。圖 6 中反白的行顯示了可最佳化的代碼。第一行使用了一個不必要的平方根,而第二行對於 while 迴圈是不變的。

 Figure 6 Code-Level Optimizations

原始代碼

複製代碼

for (int column = 1; column < Width; column++){ y = yStart; for (int row = 1; row < Height; row++) {  double x1 = 0;  double y1 = 0;  int color = 0;  int dept = 0;  while (dept < 100 && Math.Sqrt((x1 * x1) + (y1 * y1)) < 2)  {   dept++;   double temp = (x1 * x1) - (y1 * y1) + x;   y1 = 2 * x1 * y1 + y;   x1 = temp;   double percentFactor = dept / (100.0);   color = ((int)(percentFactor * 255));  }  //Comment this line to avoid calling Bitmap.SetPixel:  //bitmap.SetPixel(column, row, colors[color]);  //Uncomment the block below to avoid Bitmap.SetPixel:  rgbValues[row * Width + column] = colors[color].ToArgb();  y += deltaY; } x += deltaX;}

最佳化後的代碼

複製代碼

for (int column = 1; column < this.Width; ++column){ y = yStart; int index = column; for (int row = 1; row < Height; row++) {  double x1 = 0;  double y1 = 0;  int dept = 0;  double x1Sqr, y1Sqr;  while (dept < 100 && ((x1Sqr = x1 * x1) + (y1Sqr = y1 * y1)) < 4)  {   dept++;   double temp = x1Sqr - y1Sqr + x;   y1 = 2 * x1 * y1 + y;   x1 = temp;  }  rgbValues[index] = colors[((int)(dept * 2.55))].ToArgb();  index += Width;  y += deltaY; } x += deltaX;}  

修改後,重新分析應用程式並檢查最佳化後代碼的效能。產生和運行應用程式後,現在在 1-2 秒內就能重新繪製不規則圖形。因而顯著減少了應用程式的啟動時間。Visual Studio 2008 包含一個可比較兩個效能報告的新功能。為實際瞭解此功能,我們在分析器中重新運行應用程式並捕獲最新的效能報告。要查看兩個應用程式版本之間的差異,在“Performance Explorer”(效能資源管理員)中選擇原始報告和最新報告。按右鍵報告,並單擊操作功能表中的“Compare Performance Reports”(比較效能報告)選項。此命令將產生一個新的報告,顯示所有函數以及兩個報告中的該函數的“Exclusive Samples %”(獨佔樣本 %)值之間的差異。由於我們削減了總體執行時間,所以 DrawMandel 的相對百分比從 31.76 上升到 70.46。為更好地查看實際最佳化效果,將比較選項窗格中的列更改為“Inclusive Samples”(包含樣本)(請參見 圖 7)。同時將閾值增加到 1500 個樣本以忽略微小的波動。此外,您可能已注意到:在預設情況下,報告顯示負數或首先顯示最佳化最少的函數(因為它常用於尋找效能下降)。但是,出於最佳化目的,我們將反向排序 Delta 列,以便可以在頂部看到最佳化的函數。請注意,DrawMandel 及其子函數的樣本數從 2,064 變為 175。超過了十倍的最佳化!為展示所取得的效能改進,可複製並粘貼該報告的任何部分。Figure 7  比較 DrawMandel 的最佳化結果 (單擊該映像獲得較大視圖)

目標分析報告可視化選項Visual Studio 可 使用以下各種效能報告選項以多種方式查看效能資料:“Call Tree”(調用樹)、“Modules”(模組)、“Functions”(函數)以及其他選項。開啟報告時預設顯示“Summary”(摘要)視圖。例如,要在 Visual Studio 2008 中尋找產生大多數處理的調用路徑,請從“Current View”(當前視圖)菜單選擇“Call Tree”(調用樹)視圖。(在 Visual Studio 2005 中,在報告底部選擇“調用樹”選項卡。)“Call Tree”(調用樹)視圖包含所有呼叫堆疊的彙總樹。“Inclusive Samples %”(包含樣本 %)列顯示這些代碼路徑中每個分支的總開銷。沿著開銷最大的分支,就可以找到效能瓶頸。在 Visual Studio 2008 中,分析器團隊添加了兩個新的功能來簡化效能報告的使用。添加的第一個功能是降噪選項。預設情況下,報告現在會裁掉不重要的小函數,從而使使用者能很容易地查看具有更大影響的函數。此選項通常稱為剪裁。另外,團隊通過將自身不進行任何處理而只調用其他函數進行處理的函數放到一起,從而減少了調用樹的深度。Visual Studio 分析器將其稱為摺疊。效能報告中的降噪選項控制剪裁和摺疊的閾值。如果在效能報告中尋找特定函數時遇到問題,則可關閉降噪選項。對 Visual Studio 2008 中調用樹的第二個較大的改進是“Hot Path”(熱路徑)按鈕和相應操作功能表。“熱路徑”會反白程式中開銷最大的代碼路徑,並沿著該路徑向下直至看到單個函數所執行(並且不是委派)的重大處理。然後,“熱路徑”會反白該函數。如果有兩個或多個單獨的重要代碼路徑,則“熱路徑”將停在樹中出現分支的位置。如果“熱路徑”為應用程式提供了多個分支,則可選擇最感興趣的一個,並對該特定分支重新應用“熱路徑”。

到目前為止,我們已示範了如何使用 Visual Studio 分析器來改善應用程式的效能。但是,許多實際應用程式都需要執行多個使用者操作才能瞭解效能問題。通常,您可能寧願忽略在開始分析前收集的所有資料。此外,可能希望在單次運行中從多種情形收集資料。為示範如何針對此類情況流量分析器,我們將切換話題並分析一個樣本電子商務網站(實際上,我們使用的是一個修改版本的 TheBeerHouse 樣本,可從 asp.net/downloads/starter-kits/the-beer-house 獲得該樣本)。此網站的載入時間很長,但由於這是一次性開銷,因此我們對啟動時間的興趣不大,而是對需要花很長時間才能載入產品目錄的原因以及將項目添加到購物車非常慢的原因更感興趣。根據本文目的,我們將僅展示對第一種情形的調查。但是,我們將針對這兩種情形收集資料,並向您展示如何篩選資料以重點關注特定情形的效能問題。首先,建立一個新的分析會話。如前所述,通過“Analyze”(分析)菜單啟動“Performance Wizard”(效能嚮導),然後通過嚮導頁面選擇預設值。請注意,對於網站,“Instrumentation Profiling”(檢測分析)是預設選項。網站一般不受 CPU 限制,通常依靠資料庫伺服器應用程式來承擔繁重的任務。因此,檢測是更好的選項。建立效能會話後,在分析器中啟動網站,但是我們將避免啟動時間並且一次僅關注一種情形。為此,在 Visual Studio 2008 的“Performance Explorer”(效能資源管理員)中,可使用“Launch with Profiling Paused”(啟動並暫停分析)選項來啟動附加有 Visual Studio 分析器的應用程式,但是分析器在使用者恢複分析之前不會收集任何資料(請參見圖 8)。Figure 8 啟動時暫停分析器 當網站正在載入時,切換回 Visual Studio。請注意,Visual Studio 分析器顯示一個名為“Data Collection Control”(資料收集控制)的新工具視窗。此視窗允許您多次暫停和恢複收集。該控制的一個重要部分是預定義標記列表。它們是可插入分析資料來指出感興趣的時間點的書籤或標籤。我們使用這些標記來分隔每個使用者情形的開頭和結尾。首先,使用操作功能表中的“Rename Mark”(重新命名標記)命令來重新命名四個標記。並刪除未使用的標記(請參見圖 9)。到目前為止,我們已暫停分析以避免啟動時間收集並準備我們的情形。網站載入完畢後,恢複分析。Figure 9 為測試情形命名分析標記 我們已做好開始第一個情形的準備。通過選擇 Product Catalog Request 標記並單擊“Insert Mark”(插入標記)按鈕,標記該情形的開頭。然後切換回 Internet Explorer,通過顯示產品目錄完成第一個情形。網站顯示產品目錄後,插入 Product Catalog Rendered 標記來指明此情形的結尾。要轉換到下一個情形,選擇 Beer cap 產品。再次在添加前後插入各自的標記。此時即完成所有情形,然後退出應用程式。完成資料分析後,Visual Studio 分析器顯示“Performance Report Summary”(效能報告摘要)。此報告與採樣報告稍有不同,因為它顯示的是調用次數最多的函數以及時間最長函數的期間。值得注意的是,此資料是在整個應用程式的生存期彙總的,並且包括以上兩個情形和所有之前的活動。顯然,我們希望效能報告只向我們顯示給定情形的資料,並且篩選出其餘部分。在 Visual Studio 2008 中,分析器具有一個新的“Marks”(標記)視圖可列出所有插入的標記。(請注意,Visual Studio 分析器將其他自動標籤插入程式的開頭和結尾)。要為第一個情形建立篩選器,選擇表明該情形開頭和結尾的標記,然後在操作功能表中選擇“Add Filter on Marks”(針對標記添加篩選器)。從而自動建立所需的篩選器(請參見圖 10)。除標記外,也可按線程、進程或時間間隔進行篩選。設定篩選器後,可繼續執行它。Figure 10 效能測試的目標程式 (單擊該映像獲得較大視圖)請注意,此篩選適用於效能報告中的所有視圖。這也是 Visual Studio 分析器自動顯示已篩選資料的新摘要頁面的原因。此摘要頁面特定於產品目錄呈現情形。例如,可以看到 System.IDisposable.Dispose 花了 3.4 秒或 61% 的情形執行時間,而之前需要 41%。通過篩選,我們可以準確地看出此函數對於特定問題的重要程度。現在修複此效能問題。需在代碼中找到處理這些對象的函數。最簡單的方法是使用“調用樹”和“熱路徑”功能(如圖 11 所示)。它會立即顯示是 SetInputControlsHighlight 函數引起對 IDisposable.Dispose 的大多數調用。Figure 11 使用熱路徑尋找問題 (單擊該映像獲得較大視圖)事實證明該函數包含一個效率很低的日誌記錄機制:

複製代碼

foreach (Control ctl in container.Controls) {  log += "Setting up control: " + ctl.ClientID;  string tempDir =     Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);  using (StreamWriter sw = new StreamWriter(    Path.Combine(tempDir, "WebSite.log"), true)) {    sw.WriteLine(log);  } ...

它是在調試過程中錯誤留下的大量日誌並且不再用於任何特定診斷目的,因此可以放心地將其刪除。同樣,Visual Studio 2008 中的“熱路徑”功能可讓我們快速確定應用程式中的瓶頸。無論您是用本機 C/C++、C# 還是 Visual Basic 來編寫應用程式,Visual Studio 分析器都能顯著簡化效能調查,並協助您編寫更快更有效應用程式。Visual Studio 2008 為 Visual Studio 分析器帶來了更多改進功能,因而可比以往更輕鬆地找出應用程式中的效能瓶頸。 from:http://msdn.microsoft.com/zh-cn/magazine/cc337887.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.