為什么要寫篇文章
談到ASP.NET應用的開發,使我不禁想起之前有朋友對我說過的一句話:做網站沒有任何的技術含量。后來他告訴我,做網站,在.NET平臺上面很簡單,不就是拖幾個控件,搞點布局,寫點js,然后敲上幾個數據的增刪查改就完了,系統大了,就多敲幾個。當時,朋友之所以說這樣的話,是與他的公司與項目背景相關的。
在很多的外包公司里面,常常用ASP.NET來快速的搭建一個Web應用,例如OA系統,企業門戶,管理系統,而這些系統往往都注重在業務流程上面,不會在其他方面關注過多,例如,性能,使用這些系統的用戶也不多,頂多幾千個,所以對于很多真正觸及到Web應用的要考慮的問題,例如,高并發,高性能,穩定,安全等,沒有接觸到。后來,我去了其他的公司,接觸到那種承受百萬,千萬級訪問量的應用的時候,越發覺得自己有很多的知識需要學習。
在與朋友共事的一些項目中,很多項目的性能都很差,我們大家都想解決這個問題,但是都沒有辦法,僅僅只是知道一些基本的措施,很多都是從網絡上面“道聽途說”,例如用stringbuilder來拼接字符串,盡量用for而不是foreach。其實說到底,還是我們對.NET不夠深入,雖然說,我們在.NET平臺上面做了很多的項目,其實很多的應用只是在.NET平臺的表層開發。(由此可見,“題海戰術”不一定能夠練就解題高手,也不一定能夠練就解決問題的思維。)
其實性能優化問題,不僅僅只是Web應用獨有的,而是說,在Web應用中,可能關注的多一點。本篇文章談的是ASP.NET應用的性能優化,其實,從本質上面,還是談的.NET應用的優化。對于其他平臺的朋友,也是非常有參考價值的。
在本篇文章中,不會談及很多的調優的方法理論(其實這些方法論是很有作用的),我會從談及一些實際,可操作性的知識,讓朋友們學而即用,同時也讓朋友對開始對.NET加深認識。
本篇的內容從以下幾個方面進行展開:內存瓶頸分析,CPU瓶頸分析,緩存分析,資源等待分析,數據庫瓶頸分析,HTTP優化。
首先來看看內存瓶頸分析。雖然,我在之前的一篇稿子《.NET企業級開發》中談 這個問題,但是,為了本篇文章的完整性,我還是提一下,同時也將這個問題講更全面一些。
內存瓶頸分析
內存性能問題可以分為兩個部分:內部內存壓力,外部內存壓力。其中內部內存壓力主要是站點本身在運行的過程中消耗過多的內存,基本是可以從托管資源,非托管資源兩方面分析;而外部內存壓力指代站點所在的服務器上面的其他應用于站點本身之間進行資源的爭奪,從而使得站點可以使用的內存太少。那么在ASP.NET企業級應用中,我們技術人員關注點可以放在內部內存壓力。
首先看看托管資源的問題。
為什么要討論托管資源?因為托管資源(就是分配中在托管堆上面的對象),分配在托管堆上,而托管堆在內存中,所有托管資源的合理的分配和回收,會對內存產生影響。
ASP.NET應用的功能就是由很多的對象組合完成的,所以討論托管資源很有必要。
在.NET中,托管堆分為兩類:大對象托管堆,小對象托管堆。一般而言,如果對象所占的空間小于85K,就分配在小堆上面,反之,分配在大堆上面。如圖的小堆圖:
在對上面,對象被劃分為三代:0,1,2代。“代”數越大,被回收的可能性就越小。基于這個理論,就要避免原本只要是低代的對象變為高代的對象,例如某個對象用完之后就銷毀的,原本是0代的,現在存活到了2代,那么它所占的內存就浪費了。雖然,垃圾回收機制沒有在一定程度上回收,但是如果我們總是“霸占”著對象,垃圾回收也沒有辦法。
下面,舉個例子,形象的說明一下。對于一個大型的ASP.NET應用而言,里面會包含很多的對象,假設10000個,其中每次請求都要產生的100個臨時對象。如果這些臨時對象,被不合理的分配,成為了大代的對象,我們來算一算。
如果這個100個對象每個占1k的空間,那么100個,我們約等于0.1M,如果站點訪問量是10w,那么如果這些0.1乘以10w,如果訪問量是100w,1000w,結果如何?大家已經清楚了。很多,需要將問題放大來看,結果就很清晰了。
對于對象的使用,有一點要記住:盡可能遲的分配,盡可能早的釋放。
下面,我們可以談談,如何找出內存問題。
可以采用工具加分析的方式。可以采用System Counter,CLR Profiler,ANTS Memory Profiler(Red Gate)等。其中System Counter,CLR Profiler分析的比較的粗糙,ANTS Memory Profiler(Red Gate)可以指出是哪段代碼有問題,方便解決問題。如圖
本篇由于篇幅的限制,先到這里,下一篇,我們可以看看一些常見的性能問題,例如字符串相關問題,Session,緩存,對象池。