編寫高性能.net代碼--性能評估及工具
昨天腦圖有背景色,影響閱讀,今天調(diào)整了下



1 性能評估及工具
●1.1 選擇評估內(nèi)容
●舉個例子:內(nèi)存
在做性能優(yōu)化計劃或研究時,應(yīng)該自上而下地進行。先確保程序結(jié)構(gòu)和算法的合理性,再往下面幾層推進。宏觀的優(yōu)化(macro-optimization)總是比微觀優(yōu)化(micro-optimization)更加有效
●好的指標(biāo)--可測量的數(shù)字
差的目標(biāo):用戶界面應(yīng)該響應(yīng)迅速。好的目標(biāo):任何操作都不會阻塞UI線程超過20 ms。但只是能被量化還不夠,還需要十分精確,正如前面的內(nèi)存優(yōu)化案例中所述。差的目標(biāo):內(nèi)存占用應(yīng)該小于1 GB。好的目標(biāo):當(dāng)負(fù)載為每秒100個請求時,工作集內(nèi)存的占用不能超過1 GB。
●目標(biāo)值的決定因素--應(yīng)用程序的類型
帶有用戶界面的程序必須不惜一切代價保證UI線程的響應(yīng)能力,無論執(zhí)行任何任務(wù)時都應(yīng)如此。而服務(wù)器端程序每秒要處理幾十、幾百,甚至幾千個請求。它必須非常高效地完成I/O操作和數(shù)據(jù)同步,以保證吞吐量和CPU利用率的最大化。因此服務(wù)器端程序的設(shè)計完全不同于其他程序。如果某個應(yīng)用程序的基礎(chǔ)架構(gòu)先天不足,對效率問題考慮欠佳,那么再回頭去修正就很難了
●設(shè)計階段的重要性
●理解整體架構(gòu)和約束條件
在設(shè)計階段時,你需要理解整體架構(gòu)和約束條件,不然你就會遺漏一些關(guān)鍵點,這將嚴(yán)重制約程序的運行。你必須在設(shè)計階段就把性能目標(biāo)預(yù)先考慮進去
●安全性
在軟件設(shè)計階段,就得考慮安全性等很多方面的問題。性能問題也一樣,不能事后再議,必須從一開始就提出明確的目標(biāo)。要想從頭開始把一個已有的應(yīng)用程序重新設(shè)計一遍,這是不可能的,這比一開始就考慮周全要付出多得多的代價
●性能分析
在項目初始階段的性能分析,與開發(fā)完成即將進入測試階段的分析是不一樣的。在初始階段必須得保證設(shè)計的靈活性,確保技術(shù)路線在理論上能完成任務(wù),確保在架構(gòu)上沒有大的問題以免除后患。一旦項目進入測試、部署和維護階段,就得把更多的精力投入微觀優(yōu)化、具體代碼方式的分析、減少內(nèi)存占用等工作
●優(yōu)化的定律
最后,你還需要了解阿姆達(dá)爾定律(Ahmdals's Law,參見http://www.writinghighperf.net/go/3[PDF]),特別是其應(yīng)用于順序執(zhí)行程序的情況,以便能找到哪部分程序是需要優(yōu)化的。那些不能明顯改善整體性能的微觀優(yōu)化,多半是在浪費時間。為了獲得最佳效果,應(yīng)該優(yōu)先優(yōu)化那些效率最低的部分。優(yōu)化永遠(yuǎn)不可能面面俱到,得有一個明智的起點。因此,準(zhǔn)備好優(yōu)化目標(biāo),再有一套優(yōu)秀的評估系統(tǒng),這些都是十分重要的。不然你連從哪兒開始都不知道。

●1.2 平均值還是百分位值
這里有18個樣本數(shù)據(jù),平均值為17 ms,但95%百分位值遠(yuǎn)大于50ms。如果只看平均值,你也許不會注意到垃圾回收引起的延時問題,但有了百分位值,判斷就更加全面,你會發(fā)現(xiàn)垃圾回收過程有時候的性能會很差
●如果只看平均值,你也許不會注意到垃圾回收引起的延時問題,但有了百分位值,判斷就更加全面
●中間值(50%百分位值)與平均值的差距相當(dāng)大。那些占比高的數(shù)值,對平均值的影響往往較大
●對于可用性要求很高的服務(wù),百分位值通常要重要得多??捎眯砸笤礁撸枰櫾u估的百分位值就越高
●1.3 評估工具
●評估、評估、再評估
你確實可以只靠查看代碼或者直覺獲得很多經(jīng)驗,也會獲得一些哪里存在性能問題的強烈暗示。你甚至?xí)覍Φ胤?,但請徹底打消省略性能評估的念頭,除非是些微不足道的問題。原因有兩個
●精確找到性能問題所在
●不清楚出錯的頻率
●如果缺少有效的評估工具,性能的優(yōu)化就毫無意義
●Visual Studio
●Visual Studio Standalone Profiler
●在Concurrency模式下,如果使用鎖或者其他同步對象時發(fā)生了資源訪問沖突,將會把所有事件記錄在案。假如因為資源爭用導(dǎo)致了線程阻塞,利用這個模式就會知曉。關(guān)于異步編程及統(tǒng)計鎖爭用次數(shù)的詳細(xì)信息
●ETW即Event Tracing for Windows,是由操作系統(tǒng)提供的事件日志,速度很快,效率也很高。所有應(yīng)用程序都會生成事件,探查器(Profiler)可以捕獲這些事件進行各種分析。第8章介紹了如何在應(yīng)用程序中充分利用ETW事件,包括捕獲預(yù)置事件及定義自己的事件

●1.3.2 性能計數(shù)器-- PerfMon.exe
●物理內(nèi)存
●虛擬內(nèi)存
●保留內(nèi)存
●已提交內(nèi)存
物理存在的一段內(nèi)存,既可能位于RAM中,也可能是在磁盤上
●內(nèi)存頁
內(nèi)存單位。每頁包含了多個已分配的內(nèi)存塊,內(nèi)存塊的單位通常是KB
●頁面交換
在多個虛擬內(nèi)存區(qū)域之間交換內(nèi)存頁的過程。內(nèi)存頁既可能與其他進程交換(軟交換,Soft Paging),也可能與硬盤交換(硬交換,Hard Paging)。軟交換的速度可以非常快
●調(diào)入內(nèi)存頁
把內(nèi)存頁從其他地方送入當(dāng)前進程。
●調(diào)出內(nèi)存頁
把內(nèi)存頁從當(dāng)前進程送出至其他地方,比如磁盤
●上下文切換
保存和恢復(fù)線程或進程狀態(tài)的過程。因為線程數(shù)目通常總是多于可用處理器數(shù),所以往往每秒會發(fā)生多次上下文切換
●內(nèi)核模式
該模式下允許操作系統(tǒng)修改底層硬件參數(shù),比如修改某些寄存器,或是啟用/禁用中斷。切換到內(nèi)核模式需要調(diào)用操作系統(tǒng)API,并且開銷相當(dāng)大
●用戶模式
用于執(zhí)行普通指令的非特權(quán)模式,此時無法修改系統(tǒng)底層參數(shù)
●Privileged Time
執(zhí)行特權(quán)指令(內(nèi)核模式)的時間開銷。
●Processor Time
應(yīng)用程序占用單個處理器的百分比。如果應(yīng)用程序占用了2個邏輯處理器,每個都是100%,那么本計數(shù)器值將會是200
●User Time
執(zhí)行非特權(quán)指令(用戶模式)的時間開銷

●IO Data Bytes/sec——I/O數(shù)據(jù)量
●Page Faults/sec——缺頁中斷總數(shù)
每當(dāng)有一頁內(nèi)存不在當(dāng)前內(nèi)存工作集中時,就會觸發(fā)缺頁中斷。重點是本數(shù)值既包含內(nèi)存軟缺頁(Soft Page Fault),又包含內(nèi)存硬缺頁(Hard Page Fault)。軟缺頁對性能沒什么大礙,可能是為了調(diào)取已加載但不屬于當(dāng)前進程的內(nèi)存頁(比如屬于共享DLL的內(nèi)存頁)。硬缺頁對性能的影響則要嚴(yán)重得多,因為這意味著數(shù)據(jù)位于磁盤而非內(nèi)存中。不幸的是,你無法通過性能計數(shù)器跟蹤每個進程的硬缺頁情況,但可以利用Memory\Page Reads/sec計數(shù)器觀察到整個系統(tǒng)的硬缺頁情況。你可以將某個進程的缺頁中斷總數(shù)和系統(tǒng)的內(nèi)存讀取總頁數(shù)(硬缺頁)結(jié)合起來,進行關(guān)聯(lián)分析。通過ETW跟蹤Windows Kernel/Memory/Hard Fault事件,可以準(zhǔn)確地跟蹤某個進程的硬缺頁情況。
●Pool Nonpaged Bytes
通常這部分內(nèi)存是分配給操作系統(tǒng)和驅(qū)動程序的,用于存放不允許被頁面交換出去的數(shù)據(jù),比如線程和互斥鎖(Mutex)之類的操作系統(tǒng)對象,以及自定義數(shù)據(jù)
●Pool Paged Bytes——同樣用于存放操作系統(tǒng)數(shù)據(jù),但這些數(shù)據(jù)允許被頁面交換出去
●Private Bytes——某個進程專有的已提交虛擬內(nèi)存(未與其他進程共享)
●Virtual Bytes——進程地址空間內(nèi)已分配的內(nèi)存,有些可能是由頁面交換文件提供的,有些是與其他進程共享的,還有些內(nèi)存則是進程專有的
●Working Set——當(dāng)前駐留在物理內(nèi)存(通常是RAM)中的虛擬內(nèi)存數(shù)量
●Working Set-Private——當(dāng)前駐留在物理內(nèi)存中的進程專有內(nèi)存數(shù)量(Private Bytes)
●Thread Count——進程中的線程數(shù),且與.NET線程數(shù)無關(guān)。關(guān)于.NET線程相關(guān)的計數(shù)器
●Objects——內(nèi)核對象(kernel-owned object)數(shù)據(jù),比如事件、互斥鎖、進程、線程、信號量、臨界區(qū)
●System——上下文交換、內(nèi)存對齊修正、文件操作、進程、線程等數(shù)量

●1.3.3 ETW 事件 ?http://www.writinghighperf.net/go/6
●ETW系統(tǒng)的效率非常高,可以用最小的開銷處理大量事件
每個事件還帶有一個由Provider定義的自定義數(shù)據(jù)字段,描述了某些狀態(tài)信息。比如Runtime的垃圾回收事件會給出當(dāng)前屬于第幾代垃圾回收、是否后臺回收等信息
●內(nèi)存/硬件錯誤(Memory/Hard Fault)。
●磁盤讀取(DiskIO/Read)。
●磁盤寫入(DiskIO/Write)。
●進程啟動(Process/Start)。
●進程停止(Process/Stop)。
●TCP/IP建立連接(TcpIp/Connect)
●TCP/IP斷開連接(TcpIp/Disconnect)。
●線程啟動(Thread/Start)。
●線程停止(Thread/Stop)

●1.3.4 ?PerfView
●以下是一些我經(jīng)常被問到的PerfView使用問題
●CPU占用率在哪里顯示?●什么程序分配到的內(nèi)存最多?●已被分配最多的資源是什么?●什么原因?qū)е铝说?代垃圾回收?●第0代垃圾回收平均多久發(fā)生一次?●我的代碼JIT編譯花了多長時間?●競爭最激烈的是什么鎖?●我的內(nèi)存托管堆情況如何?
●用PerfView進行事件收集和分析的基本步驟
1.在“Collect”菜單中選擇“Collect”菜單項。2.在彈出的對話框中設(shè)置所需參數(shù)。a.展開“Advanced Options”選擇需要捕獲的事件類型,盡量縮小范圍 b.如果當(dāng)前版本不是.NET 3.5,請選中“No V3.X NGEN Symbols”勾選框。c.可以指定“Max Collect Sec”參數(shù),以便在該指定時間后自動停止收集工作。3.單擊“Start Collection”按鈕。4.如果未設(shè)置“Max Collect Sec”參數(shù),請在數(shù)據(jù)收集完成后單擊“Stop Collection”按鈕。5.等待事件分析完成。6.在結(jié)果樹中選擇各種視圖來查看結(jié)果
●PerfView貌似大多是在對內(nèi)存和CPU進行分析,但請別忘記它真的只是一個通用的調(diào)用棧收集程序,這些調(diào)用??赡軄碜匀魏蜤TW事件。PerfView可以用來分析鎖競爭的來源、磁盤I/O等所有應(yīng)用程序事件,同樣提供了強大的分組和折疊顯示能力。

●1.3.5 CLR Profiler
●1.3.6 Windbg ?很強大
●Windbg的查看功能
●內(nèi)存堆中每一類對象的數(shù)量有多少
●每個內(nèi)存堆有多大,哪些是空閑的(碎片情況)
●某次垃圾回收之后還有哪些對象駐留著
●哪些對象是被固定的(Pinned)
●哪些線程的CPU耗時最多,是否有線程陷入了死循環(huán)
●1.3.7 .NET IL分析器
●反編譯軟件Reflector、ILSpy、dotPeek
●1.3.8 MeasureIt
●微型性能基準(zhǔn)測試工具; 分別顯示各種.NetAPI的相對開銷,包括調(diào)用,數(shù)組、委托Delegates、迭代Iteration、反射Reflection
●MeasureIt的主要用途就是,在API級別把軟件設(shè)計對性能的影響顯示出來。比如在lock類中,你會發(fā)現(xiàn)使用ReaderWriteLock會比常規(guī)的lock語句慢4倍左右
●在MeasureIt的代碼中加入自己的測試是非常容易的,它已經(jīng)自帶了源代碼,運行MeasureIt /edit就可以解包出來。通過研究這些代碼,會讓你對編寫精確的測試代碼產(chǎn)生很大啟發(fā)
●1.3.9 ?代碼中的工具
●stopwatch 更加準(zhǔn)確

●1.3.10 ?SysInternals工具
●ClockRes 顯示系統(tǒng)時鐘的精度
●Diskmon 監(jiān)視硬盤活動
●Handle 監(jiān)視進程打開了那些文件
●ProcDump 高度可定制化的進程轉(zhuǎn)儲文件生成工具
●Process Explorer 非常強大的任務(wù)管理器
●Process Monitor 實時監(jiān)視文件、注冊表、進程的活動
●VMMap 分析進程的地址空間
●1.4 小結(jié)
●提升性能的首要法則就是評估、評估、再評估
●知道該為你的應(yīng)用程序使用什么性能指標(biāo)是非常重要的,每個指標(biāo)都應(yīng)該是精確、可量化的
●平均值是很不錯,但百分位值也同樣要重視,特別是針對高可用性的服務(wù)而言
●在前期設(shè)計階段就要把性能目標(biāo)考慮在內(nèi),理解系統(tǒng)架構(gòu)對性能的影響程度。先從那些影響最大的部分開始著手優(yōu)化。首先關(guān)注算法及整體性的宏觀優(yōu)化,然后再轉(zhuǎn)移到微觀優(yōu)化中去
●應(yīng)該充分了解性能計數(shù)器和ETW事件
●要善用工具軟件進行性能分析和調(diào)試。請學(xué)習(xí)如何使用Windbg和PerfView這類最強大的工具,以便快速解決性能問題

本文使用 文章同步助手 同步