1.概述
大家經常對一個系統的容量進行評估時,會參考cpu.idle和cpu.load指標,但是這兩個指標到底在什么區間,表示系統是正常或者異常呢,業內有不同的說法。因此本文搜集一些資料,並對一個系統進行壓測,最終來獲得一個比較客觀的觀點,如有不對,可以在評論區進行交流。
在開始之前,我們必須對系統運轉有一個整體的認識。在Linux內核中,每個進程都會被分配一個固定的時間片,默認為10ms,在這10ms中,該進程享有cpu的所有權。10ms看上去很短,但以2.6GHz的Intel處理器為例,10ms能夠處理5000w條指令,對於絕大多數的應用這已經足夠長了。如果該進程用完了10ms,或者有其他優先級高的進程發出請求,系統會觸發一個中斷,內核重新接管cpu,內核分配cpu給其他進程。10ms的分片讓用戶,也就是我們覺得我們的系統運轉非常流暢,盡管我們可能同時開了很多的應用。
2.cpu.idle
CPU利用率主要分為用戶態,系統態和空閑態,分別表示CPU處於用戶態執行的時間,系統內核執行的時間,和空閑系統進程執行的時間,三者之和就是CPU的總時間,當沒有用戶進程、系統進程等需要執行的時候,CPU就執行系統缺省的空閑進程。CPU的利用率就是指非空閑進程占用時間的比例,即CPU執行非空閑進程的時間 / CPU總的執行時間。
/proc文件系統是一個偽文件系統,它只存在內存當中,而不占用外存空間。它以文件系統的方式為內核與進程提供通信的接口。用戶和應用程序可以通過/proc得到系統的信息,並可以改變內核的某些參數。由於系統的信息,如進程,是動態改變的,所以用戶或應用程序讀取/proc目錄中的文件時,proc文件系統是動態從系統內核讀出所需信息並提交的。
cpu.idle是基於/proc/stat計算出來的,首先了解一下/proc/stat的各項指標的意義。
[xietao02@gh-trip-open-opengateway-staging01 ~]$ cat /proc/stat
cpu 30512019 2905 18888929 5215060855 449961 258 322293 482253 0
cpu0 12054132 723 5666598 1297356736 439476 258 173174 175261 0
cpu1 6256562 718 4332274 1305529992 4073 0 50163 105721 0
cpu2 6252205 723 4470475 1305772598 3466 0 49552 102278 0
cpu3 5949118 739 4419581 1306401527 2944 0 49403 98992 0
intr 10488180092 119 7 0 0 0 0 0 0 1 0 0 33 104 0 0 68 0 0 0 0 0 0 0 0 0 10319942 0 336 0 18155452 0 14 0 265289852 3907 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 18254375560
btime 1516246663
processes 13216259
procs_running 1
procs_blocked 0
softirq 3948723530 0 1488253637 8488 455883603 17 0 179 392363322 13619548 1598594736
第一行的數值表示的是CPU總的使用情況,cpu0、cpu1、cpu2、cpu3分別指每個cpu核心的cpu使用情況,下表解析第一行各數值的含義(單位:jiffies):
user (30512019) |
從系統啟動開始累計到當前時刻,用戶態的CPU時間,不包含nice值為負進程。 |
nice (2905) |
從系統啟動開始累計到當前時刻,nice值為負的進程所占用的CPU時間 |
system (18888929) |
從系統啟動開始累計當前時刻,核心時間 |
idle (5215060855) |
從系統啟動開始累計到當前時刻,除IO等待時間以外其它等待時間 |
iowait (449961) |
從系統啟動開始累計到當前時刻,IO等待時間 2.5.41版本新增字段 |
irq (258) |
從系統啟動開始累計到當前時刻,硬中斷時間 2.6.0版本新增字段 |
softirq (322293) |
從系統啟動開始累計到當前時刻,軟中斷時間 2.6.0版本新增字段 |
stealstolen(482253) |
當一台物理機有多個虛擬機時,該cpu在其他虛擬機運行的時間 which is the time spent in other operating systems when running in a virtualized environment 2.6.11 |
guest(0) |
在cpu內核控制下,提供給在上面運行虛擬機占用的cpu時間 which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel 2.6.24 |
因為/proc/stat中的數值都是從系統啟動開始累計到當前時刻的積累值,所以需要在不同時間點t1和t2取值進行比較運算,當兩個時間點的間隔較短時,就可以把這個計算結果看作是CPU的即時利用率。
其他參數的含義
ctxt |
上下文切換次數 |
|
btime |
系統啟動到當前的時間 |
sec |
process |
自啟動以來,創建任務個數 |
|
procs_running |
當前運行任務個數 |
|
procs_blocked |
阻塞的任務個數 |
|
2.1 CPU的即時利用率的計算公式(top falcon命令顯示的):
CPU在t1到t2時間段總的使用時間 = ( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2+stealstolen2+guest2) - ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1+stealstolen1+guest1)
CPU在t1到t2時間段空閑使用時間 = (idle2 - idle1)
CPU在t1到t2時間段即時利用率 = 1 - CPU空閑使用時間 / CPU總的使用時間
從top命令中看到的idle和falcon看到的cpu.idle都是以上的計算結果。
從falcon上看到的cpu.busy=1-cpu.idle。
2.2 CPU的平均利用率的計算公式(sar -u和ps aux命令顯示的)
1-(當前時間對應的cpu.idle值 )/ (當前時間對應的cpu.total值),cpu.total就是cpu那一行所有項的加和。
2.3 進程和線程的cpu使用率
/proc目錄中有一些以數字命名的目錄,它們是進程目錄。系統中當前運行的每一個進程在/proc下都對應一個以進程號為目錄名的目錄/proc/pid,它們是讀取進程信息的接口。此外,在Linux 2.6.0-test6以上的版本中/proc/pid目錄中有一個task目錄,/proc/pid/task目錄中也有一些以該進程所擁有的線程的線程號命名的目錄/proc/pid/task/tid,它們是讀取線程信息的接口。
linux中的輕量級進程(lwp)即為線程,對應tid。
計算某一個進程和某一個線程的cpu利用率,和計算系統的cpu利用率類似。讀取/proc/pid/stat或者讀取/proc/pid/task/stat中的參數來進行計算。
3. cpu.load(系統平均負載,通過top、uptime、和falcon可以查看)
系統平均負載被定義為在特定時間間隔內運行隊列中(在CPU上運行或者等待運行多少進程)的平均進程數。如果一個進程滿足以下條件則其就會位於運行隊列中:
-
它沒有在等待I/O操作的結果
-
它沒有主動進入等待狀態(也就是沒有調用’wait’)
-
沒有被停止(例如:等待終止)
在Linux中,進程分為三種狀態,一種是阻塞的進程blocked process,一種是可運行的進程runnable process,另外就是正在運行的進程running process。
進程可運行狀態時,它處在一個運行隊列run queue中,與其他可運行進程爭奪CPU時間。 系統的load是指正在運行和准備好運行的進程的總數。比如現在系統有2個正在運行的進程,3個可運行進程,那么系統的load就是5。
cpu.load是基於/proc/loadavg進行統計的。
查看系統平均負載使用“cat /proc/loadavg”命令,輸出結果如下:
0.27 0.36 0.37 4/83 4828/
前三個指1、5、15分鍾內的平均進程數(可以簡單理解為每五秒統計一次,其實真實計算比較復雜。https://blog.csdn.net/jlds123/article/details/7617132)。后面兩個指(正在運行的進程數/進程總數)和最近運行的進程ID號。
另外,通過"load average"中的三個數字,我們還可以了解到當前服務器的負載的變化趨勢,如果1分鍾的CPU負載 > 5分鍾的CPU負載,說明服務器目前處在CPU負載高峰期;而如果1分鍾的CPU負載 < 5分鍾的CPU負載,則說明服務器的CPU負載高峰期剛剛過去了,如果是你處理了什么性能問題,則表明該處理已經顯現成效了。
cpu.load大於多少沒有性能夠問題呢?
理想情況下cpu不空閑,但每個線程又都能及時獲得cpu時間,沒有等待的線程,任務處理完,緊接着出現另外一個可運行線程來獲得cpu時間,此時cpu.load/cores=1。如果cpu.load過大則表示,有部分線程在等待獲得cpu資源,過小表示cpu資源比較空閑。
對於cpu.load多少開始出現性能問題,外界有不同的說法,有的認為cpu.load/cores最好不要超過1,有的認為cpu.load/cores最好不要超過3,有的認為cpu.load不超過2*cores-2即可。
針對技術商服務進行壓測時,發現load低時,接口TP999響應時間<50ms,而cpu.load/cores>4時,TP999響應時間約為200ms左右,多出來的時間可以理解為線程等待cpu處理的時間,可見cpu.load/cores過高時是影響接口響應時間的。
因此可以結合預期的接口響應時間,來定義每個服務的cpu.load/cores不超過多少。比如要求接口響應時間盡可能快的,最好確保cpu.load/cores不超過1,而對時間敏感性要求不太高時,一般要求cpu.load/cores不超過3。