文章轉自:原創: 楊建旭 https://mp.weixin.qq.com/s/gPkxJnZAI0B-vBgcR6CwyQ
有時我們說到nmon、topas、ps等幾個命令中顯示的CPU利用率不一致,那可以歸結為CPU利用率的算法不一致,其實也就是分母不一致導致(除以不同數量的CPU)。
但很多同學在看nmon中的CPU利用率的時候都表示困惑,同是一份nmon報告,好幾處出現CPU利用率的地方,為什么也不一致。由於從來就沒有什么文檔來介紹這些數據之間的關聯,本節就來解釋這些問題。
CPU_ALL和TOP頁不一致
首先我們看CPU_ALL這個Sheet,CPU利用率大概是75%的樣子。

有時候想知道是哪些進程占了CPU,我們就切換到TOP這個Sheet。

問題來了,占用CPU最高的進程是cicsas,平均利用率(WAvg)是17%。而其他進程最大也就2%的平均利用率,而且這樣的進程只有5個。那么總CPU利用率75%是怎么湊出來?
Avg和WAvg的區別
說這個問題之前,我們先解釋一下進程CPU利用率中Avg、WAvg的含義和區別。
Avg是這段時間內利用率的平均值。
WAvg,這個是重點,WAvg是除去0值之后的平均值。所以WAvg一定是大於等於Avg的。絕大多數情況下,我們看是WAvg而不是Avg。因為我們統計的是進程運行時候的占用情況,圖1就是一個例子。中間有不運行的時間段,統計avg是沒有意義的。
CPU_ALL和TOP的統一
言歸正傳,總CPU利用率75%是怎么湊出來?我們還得從頭說起。
TOP Sheet中按照command篩選,把那個CPU最高的進程(cicsas)選出來。我們看到15:30:52這個時間點有20個cicsas進程,可以用肉眼數出來,也可以看Threads這個列的數據。當然肉眼數的結果和Threads列顯示的結果不一定一致。因為肉眼看到的是CPU利用率排到top的進程,沒有進入top行列是不會顯示出來的。

本次nmon的監控是30秒一次,這20個進程是同一個時間點(15:30:52)監控出來的,而不是從15:30:52到15:31:12這30秒內陸陸續續監控出來的。也就是說,當前系統cicsas進程的並發數是20.
這20個cicsas進程每個進程都有24%左右的CPU利用率,它們加起來有240%,這是什么鬼?
明顯超過了100%,那么說明每個進程的CPU利用率都是針對單個CPU的利用率,而不是針對系統所有CPU的利用率。也就是說CPU利用率的計算公式中,分母是1。假如系統中有個10個CPU,有1個進程P,P占用了一整顆CPU,利用率為100%,不考慮其他進程,我們看整機的CPU_ALL中的利用率就是10%。
其實在解釋Avg的時候並沒有解釋清楚,我們繼續解釋。avg這個利用率指的是相同進程名的所有進程的平均值,另外還有一個時間維度,不同時間點的平均值再進行一次平均,就得到了Avg這個值。如果除去0值做平均,得到是WAvg這個值。
所以,在這個CPU的TOP的圖上,有時候我們看到柱子高的進程占用CPU不一定最多,因為還需要把進程的數量考慮在內。
在圖2中,WAvg是17.5%左右,由於有20個進程,它們總的CPU占用是17.5%*20=350%。而這個值是相對於單顆CPU的利用率,我們只要除以CPU總數應該就可以和CPU_ALL中的75%對應上了。此時似乎疑團散去,但問題還在后面。
好了,我們來看看這個LPAR的CPU配置,來到BBBL Sheet

8顆虛擬處理器,2個EC。
剛才計算的350%,除以8=43.75%,除以2=175%,和我們的目標75%明顯不着邊。這。。難道我們分析錯了嗎?
為了解釋清楚這件事,我們需要從CPU_ALL的算法開始說。
由於大家大腦中的CPU利用率最多是100%,不能再多了。而虛擬化之后,有超過標稱計算能力(EC)一說,比如分配了2個core的能力(EC=2),而運行當中,由於2個core的能力不夠,LPAR搶占了3個core的能力,這時候CPU利用率按理說就是150%了。事實上,topas這個命令有個Entc這個指標,大致就是這個意思。如果Entc超過100%,就說明當前占用的物理CPU的數量已經超過了預設的EC。
但NMON的設計者擔心具有傳統思維的遺老遺少接受不了150%這個現實,就把CPU利用率強行控制在100%以內。方法嘛就是增大分母,分母是多少呢?
從LPAR Sheet看出,運行時獲得的物理CPU的數量(藍色線)是動態的,而且大部分時候是超過2C的,右側有壓力的時間段,平均值大概是5。

我們的350%除以5=70%。這就和75%基本對上了。75%和70%之間的5%是cicsas這個超級CPU飯桶之外的那些小進程的消耗。
CPU_ALL和LPAR頁的統一
需要說明的是,CPU_ALL算法里面分母是動態的,因為運行時獲得物理CPU數量是動態的。
但並不是所有時候分母都是動態的。
當Physical CPU>EC時,CPU利用率=(用戶態CPU+系統態CPU)/運行時物理CPU,也就是物理CPU利用率。
當Physical CPU<=EC時,CPU利用率=(用戶態CPU+系統態CPU)/EC值。
通過這樣的算法,當Physical CPU很小,約等於0的時候,可以看到CPU利用率也基本=0,而不會出現本來沒用CPU但CPU利用率很高的誤導圖形
但不管怎么說,這個CPU_ALL還是比較誤導人。你分母是變的,我統計CPU利用率到底是多少顆CPU的利用率呢?
這里我們可以引入一個VP利用率的指標。這個指標的好處是分母是固定的,分母就是VP的數量
VP利用率=(用戶態CPU+系統態CPU)/VP值

圖中的例子,看16:11:13這個時間點
EC利用率=135.54%+53.01%=188.55%,EC=2,就是說按照2顆CPU來說,當前LPAR占用了2*188.55%=3.771顆CPU
VP利用率=33.88%+13.25%=47.13,VP=8,按照8顆CPU來說,當前LPAR占用了8*47.13%=3.7704顆CPU
而CPU_ALL中的CPU利用率=3.77/5.076=74.3%
我們跳轉到CPU_ALL Sheet看看16:11:13,CPU%果然是74.3%。

所以,對於這種physical CPU超過EC,飄忽不定的分母,是不能用CPU_ALL中的數值的,而應該用LPAR中的VP利用率=(用戶態CPU+系統態CPU)/VP值。出具統計結果的時候,可以說“在8顆CPU的時候,CPU利用率是xxx%”。