Linux 作為一個(gè)多任務(wù)操作系統(tǒng)北救,將每個(gè) CPU 的時(shí)間劃分為很短的時(shí)間片,再通過(guò)調(diào)度器輪流分配給各個(gè)任務(wù)使用牵祟,因此造成多任務(wù)同時(shí)運(yùn)行的錯(cuò)覺(jué)。
為了維護(hù) CPU 時(shí)間鄙陡,Linux 通過(guò)事先定義的節(jié)拍率(內(nèi)核中表示為 HZ),觸發(fā)時(shí)間中斷躏啰,并使用全局變量 Jiffies 記錄了開機(jī)以來(lái)的節(jié)拍數(shù)趁矾。每發(fā)生一次時(shí)間中斷,Jiffies 的值就加 1给僵。
節(jié)拍率 HZ 是內(nèi)核的可配選項(xiàng)毫捣,可以設(shè)置為 100、250帝际、1000 等蔓同。不同的系統(tǒng)可能設(shè)置不同數(shù)值,你可以通過(guò)查詢 /boot/config 內(nèi)核選項(xiàng)來(lái)查看它的配置值蹲诀。比如在我的系統(tǒng)中斑粱,節(jié)拍率設(shè)置成了 250,也就是每秒鐘觸發(fā) 250 次時(shí)間中斷脯爪。
grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=250
同時(shí)则北,正因?yàn)楣?jié)拍率 HZ 是內(nèi)核選項(xiàng),所以用戶空間程序并不能直接訪問(wèn)痕慢。為了方便用戶空間程序尚揣,內(nèi)核還提供了一個(gè)用戶空間節(jié)拍率 USER_HZ,它總是固定為 100掖举,也就是 1/100 秒快骗。這樣,用戶空間程序并不需要關(guān)心內(nèi)核中 HZ 被設(shè)置成了多少拇泛,因?yàn)樗吹降目偸枪潭ㄖ?USER_HZ滨巴。
Linux 通過(guò) /proc 虛擬文件系統(tǒng),向用戶空間提供了系統(tǒng)內(nèi)部狀態(tài)的信息俺叭,而 /proc/stat 提供的就是系統(tǒng)的 CPU 和任務(wù)統(tǒng)計(jì)信息恭取。比方說(shuō),如果你只關(guān)注 CPU 的話熄守,可以執(zhí)行下面的命令:
# 只保留各個(gè) CPU 的數(shù)據(jù)
$ cat /proc/stat | grep ^cpu
cpu 280580 7407 286084 172900810 83602 0 583 0 0 0
cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0
cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0
這里的輸出結(jié)果是一個(gè)表格蜈垮。其中,第一列表示的是 CPU 編號(hào)裕照,如 cpu0攒发、cpu1 ,而第一行沒(méi)有編號(hào)的 cpu 晋南,表示的是所有 CPU 的累加惠猿。其他列則表示不同場(chǎng)景下 CPU 的累加節(jié)拍數(shù),它的單位是 USER_HZ负间,也就是 10 ms(1/100 秒)偶妖,所以這其實(shí)就是不同場(chǎng)景下的 CPU 時(shí)間姜凄。
當(dāng)然,這里每一列的順序并不需要你背下來(lái)趾访。你只要記住态秧,有需要的時(shí)候,查詢 man proc 就可以扼鞋。不過(guò)申鱼,你要清楚 man proc 文檔里每一列的涵義,它們都是 CPU 使用率相關(guān)的重要指標(biāo)云头,你還會(huì)在很多其他的性能工具中看到它們捐友。
- user(通常縮寫為 us)盘寡,代表用戶態(tài) CPU 時(shí)間楚殿。注意,它不包括下面的 nice 時(shí)間竿痰,但包括了 guest 時(shí)間。
- system(通称瞿纾縮寫為 sys)影涉,代表內(nèi)核態(tài) CPU 時(shí)間。
- idle(通彻娣ィ縮寫為 id)蟹倾,代表空閑時(shí)間。注意猖闪,它不包括等待 I/O 的時(shí)間(iowait)鲜棠。
- iowait(通常縮寫為 wa)培慌,代表等待 I/O 的 CPU 時(shí)間豁陆。
- irq(通常縮寫為 hi)吵护,代表處理硬中斷的 CPU 時(shí)間盒音。
- softirq(通常縮寫為 si)馅而,代表處理軟中斷的 CPU 時(shí)間祥诽。
- steal(通常縮寫為 st)瓮恭,代表當(dāng)系統(tǒng)運(yùn)行在虛擬機(jī)中的時(shí)候雄坪,被其他虛擬機(jī)占用的 CPU 時(shí)間。
- guest(通惩捅模縮寫為 guest)维哈,代表通過(guò)虛擬化運(yùn)行其他操作系統(tǒng)的時(shí)間盯漂,也就是運(yùn)行虛擬機(jī)的 CPU 時(shí)間。
- guest_nice(通潮颗縮寫為 gnice)就缆,代表以低優(yōu)先級(jí)運(yùn)行虛擬機(jī)的時(shí)間。
而我們通常所說(shuō)的 CPU 使用率谒亦,就是除了空閑時(shí)間外的其他時(shí)間占總 CPU 時(shí)間的百分比竭宰,用公式來(lái)表示就是:
看到這里,你應(yīng)該想起來(lái)了份招,這是開機(jī)以來(lái)的節(jié)拍數(shù)累加值切揭,所以直接算出來(lái)的,是開機(jī)以來(lái)的平均 CPU 使用率锁摔,一般沒(méi)啥參考價(jià)值廓旬。
事實(shí)上,為了計(jì)算 CPU 使用率谐腰,性能工具一般都會(huì)取間隔一段時(shí)間(比如 3 秒)的兩次值孕豹,作差后,再計(jì)算出這段時(shí)間內(nèi)的平均 CPU 使用率十气,即
這個(gè)公式励背,就是我們用各種性能工具所看到的 CPU 使用率的實(shí)際計(jì)算方法。
現(xiàn)在砸西,我們知道了系統(tǒng) CPU 使用率的計(jì)算方法叶眉,那進(jìn)程的呢?跟系統(tǒng)的指標(biāo)類似芹枷,Linux 也給每個(gè)進(jìn)程提供了運(yùn)行情況的統(tǒng)計(jì)信息衅疙,也就是 /proc/[pid]/stat。不過(guò)鸳慈,這個(gè)文件包含的數(shù)據(jù)就比較豐富了饱溢,總共有 52 列的數(shù)據(jù)
當(dāng)然,不用擔(dān)心蝶涩,因?yàn)槟悴⒉恍枰莆彰恳涣械暮x理朋。還是那句話,需要的時(shí)候绿聘,查 man proc 就行嗽上。 回過(guò)頭來(lái)看,是不是說(shuō)要查看 CPU 使用率熄攘,就必須先讀取 /proc/stat 和 /proc/[pid]/stat 這兩個(gè)文件兽愤,然后再按照上面的公式計(jì)算出來(lái)呢?
當(dāng)然不是,各種各樣的性能分析工具已經(jīng)幫我們計(jì)算好了浅萧。不過(guò)要注意的是逐沙,性能分析工具給出的都是間隔一段時(shí)間的平均 CPU 使用率,所以要注意間隔時(shí)間的設(shè)置洼畅,特別是用多個(gè)工具對(duì)比分析時(shí)吩案,你一定要保證它們用的是相同的間隔時(shí)間。
比如帝簇,對(duì)比一下 top 和 ps 這兩個(gè)工具報(bào)告的 CPU 使用率徘郭,默認(rèn)的結(jié)果很可能不一樣,因?yàn)?top 默認(rèn)使用 3 秒時(shí)間間隔丧肴,而 ps 使用的卻是進(jìn)程的整個(gè)生命周期残揉。
怎么查看 CPU 使用率
知道了 CPU 使用率的含義后,我們?cè)賮?lái)看看要怎么查看 CPU 使用率芋浮。說(shuō)到查看 CPU 使用率的工具抱环,我猜你第一反應(yīng)肯定是 top 和 ps。的確纸巷,top 和 ps 是最常用的性能分析工具:
- top 顯示了系統(tǒng)總體的 CPU 和內(nèi)存使用情況镇草,以及各個(gè)進(jìn)程的資源使用情況。
- ps 則只顯示了每個(gè)進(jìn)程的資源使用情況何暇。
top 的輸出格式為:
# 默認(rèn)每 3 秒刷新一次
$ top
top - 11:58:59 up 9 days, 22:47, 1 user, load average: 0.03, 0.02, 0.00
Tasks: 123 total, 1 running, 72 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 8169348 total, 5606884 free, 334640 used, 2227824 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7497908 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 78088 9288 6696 S 0.0 0.1 0:16.83 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.05 kthreadd
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
需要注意陶夜,top 默認(rèn)顯示的是所有 CPU 的平均值,這個(gè)時(shí)候你只需要按下數(shù)字 1 裆站,就可以切換到每個(gè) CPU 的使用率了。
繼續(xù)往下看黔夭,空白行之后是進(jìn)程的實(shí)時(shí)信息宏胯,每個(gè)進(jìn)程都有一個(gè) %CPU 列,表示進(jìn)程的 CPU 使用率本姥。它是用戶態(tài)和內(nèi)核態(tài) CPU 使用率的總和肩袍,包括進(jìn)程用戶空間使用的 CPU、通過(guò)系統(tǒng)調(diào)用執(zhí)行的內(nèi)核空間 CPU 婚惫、以及在就緒隊(duì)列等待運(yùn)行的 CPU氛赐。在虛擬化環(huán)境中,它還包括了運(yùn)行虛擬機(jī)占用的 CPU
所以先舷,到這里我們可以發(fā)現(xiàn)艰管, top 并沒(méi)有細(xì)分進(jìn)程的用戶態(tài) CPU 和內(nèi)核態(tài) CPU。那要怎么查看每個(gè)進(jìn)程的詳細(xì)情況呢蒋川?你應(yīng)該還記得上一節(jié)用到的 pidstat 吧牲芋,它正是一個(gè)專門分析每個(gè)進(jìn)程 CPU 使用情況的工具。
比如,下面的 pidstat 命令缸浦,就間隔 1 秒展示了進(jìn)程的 5 組 CPU 使用率夕冲,包括:
- 用戶態(tài) CPU 使用率 (%usr);
- 內(nèi)核態(tài) CPU 使用率(%system)裂逐;
- 運(yùn)行虛擬機(jī) CPU 使用率(%guest)歹鱼;
- 等待 CPU 使用率(%wait);
- 以及總的 CPU 使用率(%CPU)卜高。
最后的 Average 部分弥姻,還計(jì)算了 5 組數(shù)據(jù)的平均值。
# 每隔 1 秒輸出一組數(shù)據(jù)篙悯,共輸出 5 組
$ pidstat 1 5
15:56:02 UID PID %usr %system %guest %wait %CPU CPU Command
15:56:03 0 15006 0.00 0.99 0.00 0.00 0.99 1 dockerd
...
Average: UID PID %usr %system %guest %wait %CPU CPU Command
Average: 0 15006 0.00 0.99 0.00 0.00 0.99 - dockerd