性能分析是指觀察和記錄有關應用程序行爲的度量的過程。常見的性能問題源於運行速度慢或低效的代碼,或者致使內存浪費的代碼。數據庫
大多數性能分析工具均可以歸爲:服務器
採樣式:採樣式性能分析器經過獲取運行應用程序的週期性快照(稱爲採樣),記錄每一個時間間隔內的應用程序運行狀態,包括正在執行的代碼行。一般狀況下,不會修改被測系統代碼,而傾向於採用外部透視方法。
插裝式:採用侵入式方案。併發
二者的主要區別在於,採樣式分析器在運行任何代碼時都會檢查應用程序,包括對外部庫的調用。而插裝式分析器則只從插裝代碼收集數據。ide
Visual Studio的性能分析工具對託管和非託管應用程序均適用,但對象分配跟蹤功能只對託管代碼有效。函數
使用Visual Studio對應用程序進行性能分析主要有4個步驟:工具
建立性能會話,選擇性能分析方法(CPU採樣、插裝、內存採樣或併發)及其目標
使用Performance Explorer瀏覽和設置會話屬性
發起會話,執行應用程序和性能分析器
審查性能報告中收集的數據。性能
建立實例應用程序:單元測試
1. 建立WidgetClass.cs文件,代碼以下:測試
1 namespace DemoConsole 2 { 3 public class WidgetClass 4 { 5 private string _name; 6 public string Name 7 { 8 get { return _name; } 9 set { _name = value; } 10 } 11 12 private int _id; 13 public int Id 14 { 15 get { return _id; } 16 set { _id = value; } 17 } 18 public WidgetClass(int id, string name) 19 { 20 _id = id; 21 _name = name; 22 } 23 } 24 }
2. 建立WidgetValueType.cs文件,代碼以下:spa
1 namespace DemoConsole 2 { 3 public struct WidgetValueType 4 { 5 private string _name; 6 public string Name 7 { 8 get { return _name; } 9 set { _name = value; } 10 } 11 12 private int _id; 13 public int Id 14 { 15 get { return _id; } 16 set { _id = value; } 17 } 18 public WidgetValueType(int id, string name) 19 { 20 _id = id; 21 _name = name; 22 } 23 } 24 }
3. 在Program.cs文件中添加代碼以下:
1 using System.Collections; 2 3 namespace DemoConsole 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 ProcessClasses(2000000); 10 ProcessValueTypes(2000000); 11 } 12 13 public static void ProcessClasses(int count) 14 { 15 ArrayList widgets = new ArrayList(); 16 for (int i = 0; i < count; i++) 17 { 18 widgets.Add(new WidgetClass(i, "Test")); 19 } 20 string[] names = new string[count]; 21 for (int i = 0; i < count; i++) 22 { 23 names[i] = ((WidgetClass)widgets[i]).Name; 24 } 25 } 26 27 public static void ProcessValueTypes(int count) 28 { 29 ArrayList widgets = new ArrayList(); 30 for (int i = 0; i < count; i++) 31 { 32 widgets.Add(new WidgetValueType(i, "Test")); 33 } 34 string[] names = new string[count]; 35 for (int i = 0; i < count; i++) 36 { 37 names[i] = ((WidgetValueType)widgets[i]).Name; 38 } 39 } 40 } 41 }
在對應用程序進行性能分析以前,首先須要建立一個性能會話,利用Performance Wizard建立會話,在其中肯定一系列最經常使用的設置,也能夠建立一個空的性能會話,或以某個單元測試結果爲基礎建立性能會話。
使用Performance Wizard
在VS2013的菜單欄上點擊ANALYZE-->Performance and Diagnostics打開會話,選擇Performance Wizard複選框,點擊Start按鈕,打開Performance Wizard:
選擇默認選項,下一步,選擇要分析的應用程序,而後完成。
添加空的性能會話
經過ANALYZE| Profiler| New Performance Session建立一個空的性能會話。而後手動指定會話的分析模式、目標和設置等。
從單元測試中建立性能會話
在VS2010中能夠經過單元測試建立性能會話,首先要執行該單元測試,而後再Test Results窗口中右擊該測試在上下文菜單中選擇Create Performance Session便可。
建立了性能會話以後,就能夠經過Performance Explorer對其進行瀏覽,Performance Explorer能夠用於配置和執行性能會話,以及瀏覽性能會話結果。
在Performance Explorer中有兩個目錄:Targets用於指定會話執行時所分析的應用程序對象。Reports用於列出當前會話每次執行時的結果。
不管使用哪一種方式建立會話,都須要查看和修改其中的設置,右擊會話名選擇屬性:
採樣分析是對應用程序進行性能分析的輕量級方法,它會週期性地中斷目標程序的執行,記錄正在執行的代碼並獲取調用棧快照。採樣結束後,分析報告中將包含函數調用次數之類的數據,能夠利用這些數據肯定可能成爲應用程序瓶頸或關鍵路徑的函數,而後建立一個插裝式會話分析對這些區域進行分析。
插裝是在目標碼中插入探針或標記的過程,當正常的程序流經這些插裝點時,應用程序在該點的相關數據會被記錄下來。插裝會很快生成大量數據,所以應該先用採樣模式找出潛在的問題域或熱點,再根據採樣結果對須要進一步分析的特定代碼域進行插裝。
流逝時間(Elapsed time)是指某個函數從開始運行到結束所花費的時間。應用程序時間(Application time)是指代碼實際執行時間扣除系統事件處理時間以後的估計值。若是應用程序在性能分析過程當中被另外一個應用程序打斷,那麼流逝時間還包括執行這個應用程序所花費的時間,而應用程序時間則不包含這部分時間。包含時間(Inclusive time)包括當前函數的執行時間及它所調用的函數的執行時間。獨佔時間不包括被調用函數的執行時間。
單擊Hot path中一個方法可轉到函數的詳細信息頁面:
因爲此例過於簡單,所以並未給出過多有用信息。
在頂端Current View下拉列表裏選擇Functions切換到Functions視圖,在該視圖中可以看到一些感興趣的結果:
在上面的視圖中列出了會話期間被採樣或插裝的全部函數。對於插裝式分析,該視圖顯示的是目標中被插裝且會話期間可以被調用的全部函數。對於採樣式分析,該視圖將包含應用程序訪問的全部其餘成員/程序集,此例只有採樣式分析,所以只包含後者。
下圖爲插裝式分析樣圖:
Visual Studio抽象出一些實用工具來完成性能分析工做。若是須要更多的控制或者須要將性能分析集成在自動化批處理過程當中,那麼就能夠直接使用這些實用工具。通常流程以下:
配置目標(必要時)和環境
啓動數據庫記錄引擎
運行目標應用程序
應用程序運行結束時,中止數據記錄引擎
生成會話報告
使用Visual Studio能夠對Javascript進行性能分析,首先要設置一個插裝式會話:
執行此性能分析會話時,性能分析器在收集應用程序的函數調用信息的同時也會收集JavaScript函數的性能信息。
常見的性能分析問題之調試符號
在查看性能分析報告時能夠發現,一旦函數調用被解析到了對咱們沒有任何幫助的實體,如[ntdll.dll],當應用程序使用了沒法找到調試符號的代碼時,經常會發生這種狀況,所以,咱們獲得的只是包含它的二進制文件而不是函數名。
調試符號是指帶有.pdb擴展名的文件,其中包含了調試器和性能分析器用於發現執行代碼信息的詳細狀況。Microsoft Symbol Server使咱們能夠經過Web鏈接動態地獲取所需符號文件,選擇Tools|Options指示Visual Studio使用該服務器,展開Debugging部分選擇Symbols。
常見的性能分析問題之插裝和代碼覆蓋
在運行插裝式性能分析時,確保不要對之前其用過代碼覆蓋的目標進行性能分析。代碼覆蓋以另外一種插裝形式肯定測試執行過程當中所訪問的代碼,所以它們會有衝突。若是已經進行過代碼覆蓋,能夠打開代碼覆蓋頁面取消相關選項,從新生成解決方案就能夠了。