標籤:style blog c tar ext http
解決效能問題的時候,我往往會讓客戶添加下面一些計數器進行效能收集。
- Process object下的所有計數器;
- Processor object下的所有計數器;
- System object下的所有計數器;
- Memory object下的所有計數器;
在排查效能問題的時候,重點關注如下資料:
一、Process object
Process object中的計數器可以針對目標進程分析記憶體,CPU,線程數目和handle數目。首先要確定目標進程,然後分析目標進程的下面一些計數器:
1、% Processor Time
該計數器是該進程佔用CPU資源的指標。當進程繁忙的時候,CPU平均佔用率應該在80%以內。如果超過該數值,程式可以認為發生了high CPU的問題。另外一種問題是CPU波動幅度大。雖然平均佔用率不高,但是上下跳動頻繁。在某一個短時間段裡面,會有連續高CPU的情況出現。
2、Handle Count
該計數器記錄了當前進程使用的kernel object handle數量。Kernel object是重要的系統資源。當程式進入穩定運行狀態的時候,Handle Count數量也應該維持在一個穩定的區間。如果發現Handle Count在整個程式周期內總體趨勢是連續向上,可以考慮程式是否有Handle Leak。
3、ID Process
該計數器記錄了目標進程的進程ID。你可能覺得奇怪,ID有什麼好觀察的。進程ID是用來觀察程式是否有重啟發生。比如ASP.NET背景工作處理序可能會自動回收。由於進程名都相同,只有通過進程ID來判斷是否進程有重新啟動現象。如果ID有變化,考慮程式是否發生崩潰或者Recycle。
4、Private Bytes
該計數器記錄了當前通過VirtualAlloc API Commit的Memory數量。無論是直接調用API申請的記憶體,被Heap Manager申請的記憶體,或者是CLR 的managed heap,都算在裡面。跟Handle Count一樣,如果在整個程式周期內總體趨勢是連續向上,說明有Memory Leak。
5、Virtual Bytes
該計數器記錄了當前進程申請成功的使用者態總記憶體位址,包括DLL/EXE佔用的地址和通過VirtualAlloc API Reserve的Memory Space數量,所以該計數器應該總大於Private Bytes。一般來說,Virtual Bytes跟Private Bytes的變化大致一致。由於記憶體分區的存在, Virtual Bytes跟Private Byes一般保持一個相對穩定的比例關係。當Virtual Bytes跟Private Bytes的比例關係大於2的時候,程式往往有比較嚴重的記憶體位址分區。
查看IIS支援最大的虛擬記憶體的方式如下:
二、Processor object
1、Total Instance
Processor object記錄系統中晶片的負載情況。由於普通程式並不刻意邦定到某個具體CPU上執行,所以在多CPU機器上觀察Total Instance也就足夠了。
2、% Processor Time
該計數器跟Process下的% Processor Time的意義一樣,不過這裡記錄的是所有進程帶來的晶片,而不是針對具體某一個進程。通過把這個計數器跟Process下的同名計數器一起比較,就能看出系統的高CPU問題是否是由於單一的某個進程導致的。
三、System
System object記錄系統中一個整體的統計資訊。所以不區分Instance. 通過比較System object下的counter和其他counter的變化趨勢,往往能看出一些線索
1、Context Switch/sec
Context Switch標示了系統中整體線程的調度,切換頻率。線程切換是開銷比較大的操作。頻繁的線程切換導大量CPU周期被浪費。所以看到高CPU的時候,一定要跟Context Switch一起比較。如果兩者有相同的變化趨勢,高CPU往往是由於contention導致的,而不是死迴圈。
2、Exception Dispatches/sec
Exception Dispatches表示了系統中異常派發,處理的頻繁程式。跟線程切換一樣,異常處理也需要大量的CPU開銷。分析方法跟Context Switch雷同。
3、File Data Operations/sec
File Data Operations記錄了當前系統中磁碟檔案讀寫的頻繁程度。通過觀察該計數器跟其他效能指標的變化趨勢,通常能夠判斷磁碟檔案操作是否是效能瓶頸。類似的計數器還有Network Interface\Bytes total/sec
四、Memory
Memory object記錄了當前系統中整體記憶體的統計資訊。
1、Available Mbytes與Committed Bytes
Available Mbytes記錄了當前剩餘的實體記憶體數量。Committed Bytes記錄了所有進程commit的記憶體數量。結合兩個計數器可以觀察到:
- 兩者相加可以粗數量級估計系統總體可用記憶體多少,便於估計物理配置;
- 當Available Mbytes少於100MB的時候,說明系統總體記憶體吃緊,會影響到整個系統所有進程的效能。應該考慮增加實體記憶體或者監察記憶體泄露;
- 通過比較Process\Private Bytes跟Virtual Bytes,便於進一步確認是否有記憶體泄露,判斷記憶體泄露是否是某一單個進程導致;
2、Free System Page Table Entries,Pool Paged Bytes和Pool Paged Bytes
這三個計數器可以衡量核心態空閑記憶體的數量。特別是當使用/3GB開關後,核心態記憶體位址被壓縮,容易導致核心態記憶體不足,繼而引發一些非常妖怪的問題。
3、.NET CLR Memory
.NET CLR Memory object記錄了CLR進程中跟CLR相關的記憶體資訊。該類別下的所有計數器都很有意思,而且意思也非常直接。建議用一個例子程式進行測試和研究。下面是兩個最常用的計數器。
4、Bytes in all heaps
Bytes in all heaps記錄了上次GC發生時候所統計到的,進程中不能被回收的所有CLR object佔用的記憶體空間。該計數器不是即時的,每次GC發生的時候該計數器才更新。跟同一進程的Process\Private bytes比較,可以區分出managed heap和native memory的變化情況。對於memory leak,便於區分是managed heap的leak還是native memory的leak。
5、%Time in GC
%Time in GC記錄了GC發生的頻繁程度。一般來說15%以內算比較正常。當超過20%說明GC發生過於頻繁。由於GC不僅僅帶來很高的CPU開銷,還需要掛起目標進程的CLR線程,所以高頻率GC是非常危險的。通過跟CPU利用率和其他效能指標比較,往往能夠看出GC對效能的影響。高頻率的GC往往因為:
- 負載過高;
- 不合理的架構,對記憶體使用量效率不高;
- 記憶體泄露,記憶體分區導致記憶體壓力; //(執法遇到過)
如果目標程式是ASP.NET,在ASP.NET開頭的object中,下面這些計數器對於測量ASP.NET的效能非常有用。由於不少計數器存在於多個object類別中,下面只列出具體的計數器名字,而不去對應到具體的object:
6、Application Restarts
Application Restarts記錄了ASP.NET Application Domain重啟的次數。導致ASP.NET appDomain重啟的原因往往是虛擬目錄中被修改。比如修改了web.config檔案,或者防毒程式對虛擬目錄進行掃描。通過該計數器可以觀察是否有異常的重啟現象。
7、Request Execution time
Request Execution time記錄了請求的執行時間,是衡量ASP.NET效能的最直接參數。通過該計數器的平均值來衡量效能是否合乎預期值。需要注意的地方是由於Windows並非即時系統,所以不能用峰值來衡量整體效能。比如當GC發生的時候,請求執行時間肯定都要超過GC的時間。所以平均值才是有效標準。
8、Request Current
Request Current記錄了當前正在處理的和等待處理的請求。最理想的情況是Request Current等於CPU的數量,這說明請求跟硬體資源能並發處理的能力恰好吻合,硬體投資正運行在最優狀態。但是一般說來,當負荷比較大的時候,Request Current也隨著增高。如果Request Current在一段時間內有超過10的情況,說明效能有問題。注意觀察這個時候對應的CPU情況和其他的資源。如果CPU不高,很可能是程式中有blocking發生,比如等待資料庫請求,導致請求無法及時完成。
9、Request/second
Request/second計數器記錄了每秒鐘到達ASP.NET的請求數。這是衡量ASP.NET負載的直接參數。注意觀察Request/second是否超過程式的預期輸送量。如果Request/Second有突發的波動,注意看是否有拒絕服務的攻擊。通過把Request/second,Request Current, Request Execution time和系統資源一起比較,往往能夠看出來ASP.NET整體效能的變化和各個因素之間的影響。
10、Request in Application Queue
當ASP.NET沒有空餘的背景工作執行緒來處理新進入的請求的時候,新的請求會被放到Application Queue中。當Application Queue堆積的請求也超過設定數值的時候,ASP.NET直接返回503 Server too busy錯誤,同時丟棄該請求。所以正常情況下,Request in Application Queue應該總為0,否則說明已經有請求堆積,效能問題嚴重。