本篇通過一小段代碼的console程序來進行性能的分析以及改進、直到后面的改進前、改進后性能比較結果。
先看console代碼(源代碼下載):
static void Main(string[] args) { int i = 10000; while(i-->0) { Core c=new Core(); c.Process(DateTime.Now.ToString()); } } public class Core { public void Process(string input) { //process logic string result = string.Format("{0}-{1}", DateTime.Now, input); //log to file Log(result); } public void Log(string message) { string fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log.txt"); string msg = "{Now}: {Message}"; msg = msg.Replace("{Now}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); msg = msg.Replace("{Message}", message); using (StreamWriter sw = System.IO.File.AppendText(fileName)) { sw.WriteLine(msg); sw.Flush(); sw.Close(); } } }
進行初次分析性能,操作步驟如下:
點擊“完成”按鈕,此時會自動進行分析,直接跑完控制台程序,vs2012會自動顯示出分析報告,如下:
從上面的“摘要”報告中得知
- System.IO.File.AppendText函數和System.AppDomain.get_BaseDirectory函數耗時最多,我們需要先優化這2個函數的使用(稍后再講)
- 共列出了最耗時的5個函數
報告視圖種類:
生成的報告視圖有很多種,上面所示默認的是“摘要”視圖,其他類型的視圖如下所列:
那么我們如何跟蹤這幾個耗時的函數呢?我們需要轉入“函數詳細信息”視圖,如下:
右邊紅框代表耗時分布比例,顯然上圖中Process函數占用了很大比例
下邊的紅框代表相應的代碼,並且還會紅色高亮性能損耗突出的代碼行、以及相應損耗比例(圖中的99.2%是由於這行代碼共有3個損耗點:83.3%+14.4%+1.5%)
我們需要往下跟蹤,進入最嚴重的process函數進行查看,我們click右邊紅框中的Process條,進入細化的分析界面,如下:
看來主要問題來自"Log(result)"代碼行,占了73.5%,繼續深入跟蹤,如下圖:
這下差不多了,這里比較損耗多的2行是:獲得fileName和AppendText到日志文件代碼行,分別優化:
- 獲得文件名優化
- 日志文件名是不變的,因此不用每次Log(msg)都要計算,直接extract為static的fileName變量
- AppendText優化
- 一旦牽涉到I/O操作,速度就慢,無法避免(從單行代碼的角度來看),那怎么辦?那就把結構改掉吧:
- 主程序寫入log到隊列中,由另外一個thread負責寫入到磁盤中
- 一旦牽涉到I/O操作,速度就慢,無法避免(從單行代碼的角度來看),那怎么辦?那就把結構改掉吧:
修改代碼如下:
public class Core { public void Process(string input) { //process logic string result = string.Format("{0}-{1}", DateTime.Now, input); //log to file Log(result); } private static List<string> log = new List<string>(); public static void Log(string message)//fileName去掉了,因為此時已經不需要這個變量了,因為是由其他線程負責寫入磁盤 { string msg = "{Now}: {Message}"; msg = msg.Replace("{Now}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); msg = msg.Replace("{Message}", message); log.Add(msg); } }
我們再次運行性能分析,如下:
我們比較下第一次和這一次的曲線圖:
改進后的性能明顯好於改進之前的性能。
自定義性能分析
我們可以通過修改屬性來add/remove性能指標,比如要加入某個/某些Windows計數器、收集Windows事件、收集.NET對象生命周期等,我們可以進行如下操作來進行設置:
將會生成如下更詳細的報告:
報告中會列出生成的最多的是哪種對象(本例中是string)、由哪些函數導致的分配了最多的內存、等等
在“標記”視圖中,能看到每隔500毫秒收集的windows計數器數據,如下圖就是磁盤隊列計數器的收集:
在“對象生存期”視圖中,能看到各種對象從new到dispose的所有數據,如下圖:
很牛b吧。
下面說說如何通過VS2012來對獨立運行的程序進行性能分析,其實很簡單,就下面這個圖就搞定了,大家都懂的:
再說說如何對web項目性能分析吧...
先打開web項目解決方案,然后直接進行性能分析,有人會說沒有請求操作啊,這個簡單,有多個解決辦法:
- 再開一個VS環境(無論是遠程的還是本地的),通過web負載測試來瘋狂請求
- 通過loadrunner/qtp來模擬請求
- 悲催的人工請求...
覺得有用的話幫我“推薦”click吧...