經驗7:如何找到你應用中的性能瓶頸?
TIP:關于性能調優,SSW的黃金規則是永遠不要在未經評估的請下進行任何調整,請參考:
http://rules.ssw.com.au/Management/RulesToSuccessfulProjects/Pages/NoPerformanceWithoutMetrics.aspx
你可能注意到了,目前為止我們還沒有對應用本身進行任何的修改,無論是TFS本身的Web服務或者是定制的代碼,都沒有進行過任何修改。
當客戶提出性能問題的時候,一般開發人員的反應是:難道我的代碼有問題,然后馬上根據自己臆想出來的最佳方式修改代碼,這是絕對錯誤的。在這種情況下,我們首先要考慮的是那些調整是事半功倍的,以上的調整,無論是服務器基礎架構,SQL Server還是IIS;我們的原則都是自下而上,盡量不對代碼進行修改,因為這樣我們才能最大化我們的調優結果,而且避免由于代碼修改而造成的額外測試以及可能衍生的bug。
這就是我們所說的ROI原則,對于我們的項目而言,添加索引可能改進10x的性能,但是你很難搞到10x于現在的硬件,所以SQL 數據庫調優是一定的首選。
不幸的是,在嘗試了以上所有的可能性后,我們仍然無法達到指標;是時候對代碼動手術了。我們使用了Visual Studio 中內置的Performance Wizard來進行性能評估,如下圖:
圖:VS 2010和VS 2012中的Performance Wizard
圖:VS 2013中這個功能叫做 Performance and Diagnostics
以下是我們獲取的第一份評估報告
圖:你可以很容易的分辨出我們的瓶頸在于NewWorkItem()這個API操作
對NewWorkItem()這個API我們進行了進一步分析,發現其中最耗時的操作其實是承載對象的實例化操作。這時問題來了,對這個操作我們無能為力,因為我們必須要這個承載對象才能執行需要的操作。經過了一些調研后,我們決定使用“對象池”的方式來盡量多的緩存一些預先實例化好的對象,需要的時候直接取出使用,完成后再放回去。最終這個對象池為又將性能提升了22%左右。
關于對象池技術,請參考:http://msdn.microsoft.com/en-us/library/ms751482.aspx
經驗8:如何發現那些最耗時的Web Service操作?
既然TFS是基于Web Service的,那么發現最耗時的Web Service調用也是進行調優的評估內容之一,這里我們激活了TFS的客戶端Web Service跟蹤,獲得了以下報告:
上圖中我們發現最耗時的操作是GetMetadataEx2[WorkItemTracking]操作,這其實就是NewWorkItem()中實例化對象的一個主要操作;這一分析再一次證實對象池的方向是正確的。對于這個GetMetadataEx操作,大家可能并不了解,其實這與TFS的操作機制有關:TFS的對象模型會在本地保存一個緩存,其中包括了工作項定制內容的定義(XML格式),這些數據其實非常龐大,因此造成了實例化操作的緩慢。
以下為激活跟蹤的配置:
關于客戶端跟蹤配置請參考:
http://blogs.msdn.com/b/buckh/archive/2010/04/23/how-to-see-the-tfs-server-calls-made-by-the-client.aspx
關于服務器端跟蹤配置請參考:
http://blogs.msdn.com/b/edhintz/archive/2007/03/30/tfs-client-tracing.aspx
經過了這一系列的評估后,我們嘗試了2種代碼調優方案:
1. 使用對象池技術
2. 直接調用Web Service (這樣也可以避免metadata的緩存操作)
對2種方案測試后我們發現結果很接近,經過一些討論后,我們決定使用方案1,因為方案2中我們必須使用未經微軟公開的API,這樣長遠來看存在維護風險。
故事到這里也就結束了,我們的客戶對結果很滿意,我的團隊也學到了很多。希望這些分享也能對你有幫助。
原文轉自:http://www.almnetworks.net/wp/2013/07/21/tfs-is-huge-in-china-part2/