那個沒有注意的指標就是load average,他和我一樣開始只是注意了CPU,記憶體的使用狀況,而沒有太注意這個指標,這個指標與他們通常的限制(10左右)有差別。重新測試的結果由於這個指標被要求壓低,最後的報告顯然不如原來的好看。自己也沒有深入過壓力測試,但是覺得不搞明白對將來機器配置和擴容都會有影響,因此去問了DBA和SA,得到的結果相差很大,看來不得不自己去找找問題的根本所在了。
通過下面的幾個部分的瞭解,可以一步一步的找出Load Average在壓力測試中真正的作用。
CPU時間片
為了提高程式執行效率,大家在很多應用中都採用了多線程模式,這樣可以將原來的序列化執行變為並存執行,任務的分解以及並存執行能夠極大地提高程式的運行效率。但這都是代碼層級的表現,而硬體是如何支援的呢。那就要靠CPU的時間片模式來說明這一切。程式的任何指令的執行往往都會要競爭CPU這個最寶貴的資源,不論你的程式分成了多少個線程去執行不同的任務,他們都必須排隊等待擷取這個資源來計算和處理命令。先看看單CPU的情況。下面兩圖描述了時間片模式和非時間片模式下的線程執行的情況:
圖 1 非時間片線程執行情況
圖 2 非時間片線程執行情況
在圖一中可以看到,任何線程如果都排隊等待CPU資源的擷取,那麼所謂的多線程就沒有任何實際意義。圖二中的CPU Manager只是我虛擬一個角色,由它來分配和管理CPU的使用狀況,此時多線程將會在運行過程中都有機會得到CPU資源,也真正實現了在單CPU的情況下實現同步多執行緒。
多CPU的情況只是單CPU的擴充,當所有的CPU都滿負荷運作的時候,就會對每一個CPU採用時間片的方式來提高效率。
在Linux的核心處理過程中,每一個進程預設會有一個固定的時間片來執行命令(預設為1/100秒),這段時間內進程被分配到CPU,然後獨佔使用。如果使用完,同時未到時間片的規定時間,那麼就主動放棄CPU的佔用,如果到時間片尚未完成工作,那麼CPU的使用權也會被收回,進程將會被中斷掛起等待下一個時間片。
CPU利用率和Load Average的區別
壓力測試不僅需要對業務情境的並發使用者等壓力參數作類比,同時也需要在壓力測試過程中隨時關注機器的效能情況,來確保壓力測試的有效性。當伺服器長期處於一種超負荷的情況下運行,所能接收的壓力並不是我們所認為的可接受的壓力。就好比專案經理在給一個人估工作量的時候,每天都讓這個人工作12個小時,那麼所制定的專案計劃就不是一個合理的計劃,那個人遲早會垮掉,而影響整體的項目進度。
CPU利用率在過去常常被我們這些外行認為是判斷機器是否已經到了滿負荷的一個標準,看到50%-60%的使用率就認為機器就已經壓到了臨界了。CPU利用率,顧名思義就是對於CPU的使用狀況,這是對一個時間段內CPU使用狀況的統計,通過這個指標可以看出在某一個時間段內CPU被佔用的情況,如果被佔用時間很高,那麼就需要考慮CPU是否已經處於超負荷運作,長期超負荷運作對於機器本身來說是一種損害,因此必須將CPU的利用率控制在一定的比例下,以保證機器的正常運作。
Load Average是CPU的Load,它所包含的資訊不是CPU的使用率狀況,而是在一段時間內CPU正在處理以及等待CPU處理的進程數之和的統計資訊,也就是CPU使用隊列的長度的統計資訊。為什麼要統計這個資訊,這個資訊的對於壓力測試的影響究竟是怎麼樣的,那就通過一個類比來解釋CPU利用率和Load Average的區別以及對於壓力測試的指導意義。
我們將CPU就類比為電話亭,每一個進程都是一個需要打電話的人。現在一共有4個電話亭(就好比我們的機器有4核),有10個人需要打電話。現在使用電話的規則是管理員會按照順序給每一個人輪流分配1分鐘的使用電話時間,如果使用者在1分鐘內使用完畢,那麼可以立刻將電話使用權返還給管理員,如果到了1分鐘電話使用者還沒有使用完畢,那麼需要重新排隊,等待再次分配使用。
圖 3 電話使用情境
上圖中對於使用電話的使用者又作了一次分類,1min的代表這些使用者佔用電話時間小於等於1min,2min表示使用者佔用電話時間小於等於2min,以此類推。根據電話使用規則,1min的使用者只需要得到一次分配即可完成通話,而其他兩類使用者需要排隊兩次到三次。
電話的利用率 = sum (active use cpu time)/period
每一個分配到電話的使用者使用電話時間的總和去除以統計的時間段。這裡需要注意的是是使用電話的時間總和(sum(active use cpu time)),這與佔用時間的總和(sum(occupy cpu time))是有區別的。(例如一個使用者得到了一分鐘的使用權,在10秒鐘內打了電話,然後去查詢號碼本花了20秒鐘,再用剩下的30秒打了另一個電話,那麼佔用了電話1分鐘,實際只是使用了40秒)
電話的Average Load體現的是在某一統計時間段內,所有使用電話的人加上等待電話分配的人一個平均統計。
電話利用率的統計能夠反映的是電話被使用的情況,當電話長期處於被使用而沒有的到足夠的時間休息間歇,那麼對於電話硬體來說是一種超負荷的運作,需要調整使用頻度。而電話Average Load卻從另一個角度來展現對於電話使用狀態的描述,Average Load越高說明對於電話資源的競爭越激烈,電話資源比較短缺。對於資源的申請和維護其實也是需要很大的成本,所以在這種高Average Load的情況下電話資源的長期“熱競爭”也是對於硬體的一種損害。
低利用率的情況下是否會有高Load Average的情況產生呢。理解佔有時間和使用時間就可以知道,當分配時間片以後,是否使用完全取決於使用者,因此完全可能出現低利用率高Load Average的情況。由此來看,僅僅從CPU的使用率來判斷CPU是否處於一種超負荷的工作狀態還是不夠的,必須結合Load Average來全域的看CPU的使用方式和申請情況。
所以回過頭來再看測試部對於Load Average的要求,在我們機器為8個CPU的情況下,控制在10 Load左右,也就是每一個CPU正在處理一個請求,同時還有2個在等待處理。看了看網上很多人的介紹一般來說Load簡單的計算就是2* CPU個數減去1-2左右(這個只是網上看來的,未必是一個標準)。
補充幾點:
1.對於CPU利用率和CPU Load Average的結果來判斷效能問題。首先低CPU利用率不表明CPU不是瓶頸,競爭CPU的隊列長期保持較長也是CPU超負荷的一種表現。對於應用來說可能會去花時間在I/O,Socket等方面,那麼可以考慮是否後這些硬體的速度影響了整體的效率。
這裡最好的樣板範例就是我在測試中發現的一個現象:SIP當前在處理過程中,為了提高處理效率,將控制策略以及計數資訊都放置在Memcached Cache裡面,當我將Memcached Cache配置擴容一倍以後,CPU的利用率以及Load都有所下降,其實也就是在處理任務的過程中,等待Socket的返回對於CPU的競爭也產生了影響。
2.未來多CPU編程的重要性。現在伺服器的CPU都是多CPU了,我們的伺服器處理能力已經不再按照摩爾定律來發展。就我上面提到的電話亭情境來看,對於三種不同時間需求的使用者來說,採用不同的分配順序,我們可看到的Load Average就會有不同。假設我們統計Load的時間段為2分鐘,如果將電話分配的順序按照:1min的使用者,2min的使用者,3min的使用者來分配,那麼我們的Load Average將會最低,採用其他順序將會有不同的結果。所以未來的多CPU編程可以更好的提高CPU的利用率,讓程式跑的更快。
CPU Utilization 好理解,就是CPU的利用率,75%以上就比較高了(也有說法是80%或者更高)。除了這個指標外,還要結合Load Average和Context Switch Rate來看,有可能CPU高是因為後兩個指標高導致的。
Load Average ,這個很難衡量。網上搜了一圈,還沒見到幾個合理的解釋。我100個並發使用者測試數來這兩個值是:77.534%,6.108,CPU利用率比較高,Load Average也好像有點高。後來發現了如下兩片博文:理解Load Average做好壓力測試 ,“Load Average是 CPU的 Load,它所包含的資訊不是 CPU的使用率狀況,而是在一段時間內 CPU正在處理以及等待 CPU處理的進程數之和的統計資訊,也就是 CPU使用隊列的長度的統計資訊。 ”,基本解釋了multi-process,multi-thread程式的原理。理解Linux處理器的負載均值(翻譯) ,簡單說起來就一句話:Load Average < CPU個數 * 核心數 *0.7
查看cpu的資訊:grep 'model name' /proc/cpuinfo
Context Switch Rate 。就是Process(Thread)的切換,如果切換過多,會讓CPU忙於切換,也會導致影響輸送量。《高效能伺服器架構 》這篇文章的第2節就是說的是這個問題的。究竟多少算合適。google了一大圈,沒有一個確切的解釋。Context Switch大體上由兩個部分組成:中斷和進程(包括線程)切換,一次中斷(Interrupt)會引起一次切換,進程(線程)的建立、啟用之類的也會引起一次切換。CS的值也和TPS(Transaction Per Second)相關的,假設每次調用會引起N次CS,那麼就可以得出
Context Switch Rate = Interrupt Rate + TPS* N
CSR減掉IR,就是進程/線程的切換,假如主進程收到請求交給線程處理,線程處理完畢歸還給主進程,這裡就是2次切換。也可以用CSR、IR、TPS的值代入公式中,得出每次事物導致的切換數。因此,要降低CSR,就必須在每個TPS引起的切換上下功夫,只有N這個值降下去,CSR就能降低,理想情況下N=0,但是無論如何如果N >= 4,則要好好檢查檢查。另外網上說的CSR<5000,我認為標準不該如此單一。
其他資訊:
這三個指標在LoadRunner中可以監控到;另外,在linux中,也可以用vmstat查看r(Load Arerage),in(Interrupt)和cs(Context Switch)
#vmstat 1 5
procs --------------memory------------- ----swap-- ---io-- -system------cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 244644 29156 415720 2336484 0 0 1 49 2 1 1 0 98 0
0 0 244644 29140 415720 2336484 0 0 0 28 9 115 0 0 99 1
0 0 244644 29140 415720 2336484 0 0 0 24 62 256 0 0 100 0
0 0 244644 29140 415720 2336484 0 0 0 0 5 93 0 0 100 0
0 0 244644 29140 415720 2336484 0 0 0 0 58 255 0 0 100 0
Interrupt Rate包括核心由於進程的時間片中斷。(在 Linux 2.6 中,系統時鐘每 1 毫秒中斷一次時鐘頻率,用 HZ 宏表示,定義為 1000,即每秒中斷 1000 次。系統不一樣,核心不一樣配置100、250的都有。)
核心的時鐘頻率可以通過如下命令知道
cat /boot/config-`uname -r` | grep '^CONFIG_HZ='
CONFIG_HZ=100
每秒總的時鐘中斷數就是 = cpu個數 * 核心數 * CONFIG_HZ
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
LOC: 97574747 52361843 105207680 69447653 Local timer interrupts
RES: 107368 257510 98635 186294 Rescheduling interrupts
CAL: 14174 14206 14164 194 function call interrupts
TLB: 1007949 853117 992546 591410 TLB shootdowns
可以查看中斷的類型以及次數