系統(tǒng)平均負(fù)載
系統(tǒng)平均負(fù)載:是處于可運(yùn)行或不可中斷狀態(tài)的平均進(jìn)程數(shù)。
可運(yùn)行進(jìn)程:使用 CPU 或等待使用 CPU 的進(jìn)程
不可中斷狀態(tài)進(jìn)程:正在等待某些 IO 訪問腿箩,一般是和硬件交互,不可被打斷(不可被打斷的原因是為了保護(hù)系統(tǒng)數(shù)據(jù)一致劣摇,防止數(shù)據(jù)讀取錯(cuò)誤)
查看系統(tǒng)平均負(fù)載
首先top命令查看進(jìn)程運(yùn)行狀態(tài)珠移,如下:
PID USER? ? ? PR? NI? ? VIRT? ? RES? ? SHR S? %CPU %MEM? ? TIME+ COMMAND
10760 user? 20? 0 3061604? 84832? 5956 S? 82.4? 0.6 126:47.61 Process
29424 user? 20? 0? 54060? 2668? 1360 R? 17.6? 0.0? 0:00.03 **top**
程序狀態(tài)Status進(jìn)程可運(yùn)行狀態(tài)為R,不可中斷運(yùn)行為D(后續(xù)講解 top 時(shí)會(huì)詳細(xì)說明)
top查看系統(tǒng)平均負(fù)載:
top - 13:09:42 up 888 days, 21:32,? 8 users,? load average: 19.95, 14.71, 14.01
Tasks: 642 total,? 2 running, 640 sleeping,? 0 stopped,? 0 zombie
%Cpu0? : 37.5 us, 27.6 sy,? 0.0 ni, 30.9 id,? 0.0 wa,? 0.0 hi,? 3.6 si,? 0.3 st
%Cpu1? : 34.1 us, 31.5 sy,? 0.0 ni, 34.1 id,? 0.0 wa,? 0.0 hi,? 0.4 si,? 0.0 st
...
KiB Mem : 14108016 total,? 2919496 free,? 6220236 used,? 4968284 buff/cache
KiB Swap:? ? ? ? 0 total,? ? ? ? 0 free,? ? ? ? 0 used.? 6654506 avail Mem
這里的load average就表示系統(tǒng)最近 1 分鐘末融、5 分鐘钧惧、15 分鐘的系統(tǒng)瓶頸負(fù)載。
uptime查看系統(tǒng)瓶頸負(fù)載
[root /home/user]# uptime
13:11:01 up 888 days, 21:33,? 8 users,? load average: 17.20, 14.85, 14.10
查看 CPU 核信息
系統(tǒng)平均負(fù)載和 CPU 核數(shù)密切相關(guān)勾习,我們可以通過以下命令查看當(dāng)前機(jī)器 CPU 信息:
lscpu查看 CPU 信息:
[root@Tencent-SNG /home/user_00]# lscpu
Architecture:? ? ? ? ? x86_64
CPU op-mode(s):? ? ? ? 32-bit, 64-bit
Byte Order:? ? ? ? ? ? Little Endian
CPU(s):? ? ? ? ? ? ? ? 8
...
L1d cache:? ? ? ? ? ? 32K
L1i cache:? ? ? ? ? ? 32K
L2 cache:? ? ? ? ? ? ? 4096K
NUMA node0 CPU(s):? ? 0-7? // NUMA架構(gòu)信息
cat /proc/cpuinfo查看每個(gè) CPU 核的信息:
processor? ? ? : 7? // 核編號(hào)7
vendor_id? ? ? : GenuineIntel
cpu family? ? ? : 6
model? ? ? ? ? : 6
...
系統(tǒng)平均負(fù)載升高的原因
一般來說浓瞪,系統(tǒng)平均負(fù)載升高意味著 CPU 使用率上升。但是他們沒有必然聯(lián)系巧婶,CPU 密集型計(jì)算任務(wù)較多一般系統(tǒng)平均負(fù)載會(huì)上升乾颁,但是如果 IO 密集型任務(wù)較多也會(huì)導(dǎo)致系統(tǒng)平均負(fù)載升高但是此時(shí)的 CPU 使用率不一定高,可能很低因?yàn)楹芏噙M(jìn)程都處于不可中斷狀態(tài)艺栈,等待 CPU 調(diào)度也會(huì)升高系統(tǒng)平均負(fù)載英岭。
所以假如我們系統(tǒng)平均負(fù)載很高,但是 CPU 使用率不是很高湿右,則需要考慮是否系統(tǒng)遇到了 IO 瓶頸诅妹,應(yīng)該優(yōu)化 IO 讀寫速度。
所以系統(tǒng)是否遇到 CPU 瓶頸需要結(jié)合 CPU 使用率,系統(tǒng)瓶頸負(fù)載一起查看(當(dāng)然還有其他指標(biāo)需要對(duì)比查看吭狡,下面繼續(xù)講解)
案例問題排查
stress是一個(gè)施加系統(tǒng)壓力和壓力測(cè)試系統(tǒng)的工具尖殃,我們可以使用stress工具壓測(cè)試 CPU,以便方便我們定位和排查 CPU 問題划煮。
yum install stress // 安裝stress工具
stress 命令使用
// --cpu 8:8個(gè)進(jìn)程不停的執(zhí)行sqrt()計(jì)算操作
// --io 4:4個(gè)進(jìn)程不同的執(zhí)行sync()io操作(刷盤)
// --vm 2:2個(gè)進(jìn)程不停的執(zhí)行malloc()內(nèi)存申請(qǐng)操作
// --vm-bytes 128M:限制1個(gè)執(zhí)行malloc的進(jìn)程申請(qǐng)內(nèi)存大小
stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10s
我們這里主要驗(yàn)證 CPU送丰、IO、進(jìn)程數(shù)過多的問題
CPU 問題排查
使用stress -c 1模擬 CPU 高負(fù)載情況般此,然后使用如下命令觀察負(fù)載變化情況:
uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:
# -d 參數(shù)表示高亮顯示變化的區(qū)域
$ watch -d uptime
... load average: 1.00, 0.75, 0.39
mpstat:使用mpstat -P ALL 1則可以查看每一秒的 CPU 每一核變化信息蚪战,整體和top類似,好處是可以把每一秒(自定義)的數(shù)據(jù)輸出方便觀察數(shù)據(jù)的變化铐懊,最終輸出平均數(shù)據(jù):
13:14:53? ? CPU? ? %usr? %nice? ? %sys %iowait? ? %irq? %soft? %steal? %guest? %gnice? %idle
13:14:58? ? all? 12.89? ? 0.00? ? 0.18? ? 0.00? ? 0.00? ? 0.03? ? 0.00? ? 0.00? ? 0.00? 86.91
13:14:58? ? ? 0? 100.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00
13:14:58? ? ? 1? ? 0.40? ? 0.00? ? 0.20? ? 0.00? ? 0.00? ? 0.20? ? 0.00? ? 0.00? ? 0.00? 99.20
由以上輸出可以得出結(jié)論,當(dāng)前系統(tǒng)負(fù)載升高瞎疼,并且其中 1 個(gè)核跑滿主要在執(zhí)行用戶態(tài)任務(wù)科乎,此時(shí)大多數(shù)屬于業(yè)務(wù)工作。所以此時(shí)需要查哪個(gè)進(jìn)程導(dǎo)致單核 CPU 跑滿:
pidstat:使用pidstat -u 1則是每隔 1 秒輸出當(dāng)前系統(tǒng)進(jìn)程贼急、CPU 數(shù)據(jù):
13:18:00? ? ? UID? ? ? PID? ? %usr %system? %guest? ? %CPU? CPU? Command
13:18:01? ? ? ? 0? ? ? ? 1? ? 1.00? ? 0.00? ? 0.00? ? 1.00? ? 4? systemd
13:18:01? ? ? ? 0? 3150617? 100.00? ? 0.00? ? 0.00? 100.00? ? 0? stress
...
top:當(dāng)然最方便的還是使用top命令查看負(fù)載情況:
top - 13:19:06 up 125 days, 20:01,? 3 users,? load average: 0.99, 0.63, 0.42
Tasks: 223 total,? 2 running, 221 sleeping,? 0 stopped,? 0 zombie
%Cpu(s): 14.5 us,? 0.3 sy,? 0.0 ni, 85.1 id,? 0.0 wa,? 0.0 hi,? 0.0 si,? 0.0 st
KiB Mem : 16166056 total,? 3118532 free,? 9550108 used,? 3497416 buff/cache
KiB Swap:? ? ? ? 0 total,? ? ? ? 0 free,? ? ? ? 0 used.? 6447640 avail Mem
? ? PID USER? ? ? PR? NI? ? VIRT? ? RES? ? SHR S? %CPU %MEM? ? TIME+ COMMAND
3150617 root? ? ? 20? 0? 10384? ? 120? ? ? 0 R 100.0? 0.0? 4:36.89 stress
此時(shí)可以看到是stress占用了很高的 CPU茅茂。
IO 問題排查
我們使用stress -i 1來模擬 IO 瓶頸問題,即死循環(huán)執(zhí)行 sync 刷盤操作:uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:
$ watch -d uptime
...,? load average: 1.06, 0.58, 0.37
mpstat:查看此時(shí) IO 消耗太抓,但是實(shí)際上我們發(fā)現(xiàn)這里 CPU 基本都消耗在了 sys 即系統(tǒng)消耗上空闲。
Average:? ? CPU? ? %usr? %nice? ? %sys %iowait? ? %irq? %soft? %steal? %guest? %gnice? %idle
Average:? ? all? ? 0.33? ? 0.00? 12.64? ? 0.13? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? 86.90
Average:? ? ? 0? ? 0.00? ? 0.00? 99.00? ? 1.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00
Average:? ? ? 1? ? 0.00? ? 0.00? ? 0.33? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? 99.67
IO 無法升高的問題:
iowait 無法升高的問題,是因?yàn)榘咐?stress 使用的是 sync()系統(tǒng)調(diào)用走敌,它的作用是刷新緩沖區(qū)內(nèi)存到磁盤中碴倾。對(duì)于新安裝的虛擬機(jī),緩沖區(qū)可能比較小掉丽,無法產(chǎn)生大的 IO 壓力跌榔,這樣大部分就都是系統(tǒng)調(diào)用的消耗了。所以捶障,你會(huì)看到只有系統(tǒng) CPU 使用率升高僧须。解決方法是使用 stress 的下一代 stress-ng,它支持更豐富的選項(xiàng)项炼,比如stress-ng -i 1 --hdd 1 --timeout 600(--hdd 表示讀寫臨時(shí)文件)担平。
Average:? ? CPU? ? %usr? %nice? ? %sys %iowait? ? %irq? %soft? %steal? %guest? %gnice? %idle
Average:? ? all? ? 0.25? ? 0.00? ? 0.44? 26.22? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? 73.09
Average:? ? ? 0? ? 0.00? ? 0.00? ? 1.02? 98.98? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00? ? 0.00
pidstat:同上(略)
可以看出 CPU 的 IO 升高導(dǎo)致系統(tǒng)平均負(fù)載升高。我們使用pidstat查找具體是哪個(gè)進(jìn)程導(dǎo)致 IO 升高的锭部。
top:這里使用 top 依舊是最方面的查看綜合參數(shù)暂论,可以得出stress是導(dǎo)致 IO 升高的元兇。
pidstat 沒有 iowait 選項(xiàng):可能是 CentOS 默認(rèn)的sysstat太老導(dǎo)致空免,需要升級(jí)到 11.5.5 之后的版本才可用空另。
進(jìn)程數(shù)過多問題排查
進(jìn)程數(shù)過多這個(gè)問題比較特殊,如果系統(tǒng)運(yùn)行了很多進(jìn)程超出了 CPU 運(yùn)行能蹋砚,就會(huì)出現(xiàn)等待 CPU 的進(jìn)程扼菠。使用stress -c 24來模擬執(zhí)行 24 個(gè)進(jìn)程(我的 CPU 是 8 核)uptime:使用uptime查看此時(shí)系統(tǒng)負(fù)載:
$ watch -d uptime
...,? load average: 18.50, 7.13, 2.84
mpstat:同上(略)
pidstat:同上(略)
可以觀察到此時(shí)的系統(tǒng)處理嚴(yán)重過載的狀態(tài)摄杂,平均負(fù)載高達(dá) 18.50。
top:我們還可以使用top命令查看此時(shí)Running狀態(tài)的進(jìn)程數(shù)循榆,這個(gè)數(shù)量很多就表示系統(tǒng)正在運(yùn)行析恢、等待運(yùn)行的進(jìn)程過多。
總結(jié)
通過以上問題現(xiàn)象及解決思路可以總結(jié)出:
平均負(fù)載高有可能是 CPU 密集型進(jìn)程導(dǎo)致的
平均負(fù)載高并不一定代表 CPU 使用率高秧饮,還有可能是 I/O 更繁忙了
當(dāng)發(fā)現(xiàn)負(fù)載高的時(shí)候映挂,你可以使用 mpstat、pidstat 等工具盗尸,輔助分析負(fù)載的來源
總結(jié)工具:mpstat柑船、pidstat、top和uptime
CPU 上下文切換
CPU 上下文:CPU 執(zhí)行每個(gè)任務(wù)都需要知道任務(wù)從哪里加載泼各、又從哪里開始運(yùn)行鞍时,也就是說,需要系統(tǒng)事先幫它設(shè)置好 CPU 寄存器和程序計(jì)數(shù)器(Program Counter扣蜻,PC)包括 CPU 寄存器在內(nèi)都被稱為 CPU 上下文逆巍。
CPU 上下文切換:CPU 上下文切換,就是先把前一個(gè)任務(wù)的 CPU 上下文(也就是 CPU 寄存器和程序計(jì)數(shù)器)保存起來莽使,然后加載新任務(wù)的上下文到這些寄存器和程序計(jì)數(shù)器锐极,最后再跳轉(zhuǎn)到程序計(jì)數(shù)器所指的新位置,運(yùn)行新任務(wù)芳肌。
CPU 上下文切換:分為進(jìn)程上下文切換灵再、線程上下文切換以及中斷上下文切換。
進(jìn)程上下文切換
從用戶態(tài)切換到內(nèi)核態(tài)需要通過系統(tǒng)調(diào)用來完成庇勃,這里就會(huì)發(fā)生進(jìn)程上下文切換(特權(quán)模式切換)檬嘀,當(dāng)切換回用戶態(tài)同樣發(fā)生上下文切換。
一般每次上下文切換都需要幾十納秒到數(shù)微秒的 CPU 時(shí)間责嚷,如果切換較多還是很容易導(dǎo)致 CPU 時(shí)間的浪費(fèi)在寄存器鸳兽、內(nèi)核棧以及虛擬內(nèi)存等資源的保存和恢復(fù)上,這里同樣會(huì)導(dǎo)致系統(tǒng)平均負(fù)載升高罕拂。
Linux 為每個(gè) CPU 維護(hù)一個(gè)就緒隊(duì)列揍异,將 R 狀態(tài)進(jìn)程按照優(yōu)先級(jí)和等待 CPU 時(shí)間排序,選擇最需要的 CPU 進(jìn)程執(zhí)行爆班。這里運(yùn)行進(jìn)程就涉及了進(jìn)程上下文切換的時(shí)機(jī):
進(jìn)程時(shí)間片耗盡衷掷、。
進(jìn)程在系統(tǒng)資源不足(內(nèi)存不足)柿菩。
進(jìn)程主動(dòng)sleep戚嗅。
有優(yōu)先級(jí)更高的進(jìn)程執(zhí)行。
硬中斷發(fā)生。
線程上下文切換
線程和進(jìn)程:
當(dāng)進(jìn)程只有一個(gè)線程時(shí)懦胞,可以認(rèn)為進(jìn)程就等于線程替久。
當(dāng)進(jìn)程擁有多個(gè)線程時(shí),這些線程會(huì)共享相同的虛擬內(nèi)存和全局變量等資源躏尉。這些資源在上下文切換時(shí)是不需要修改的蚯根。
線程也有自己的私有數(shù)據(jù),比如棧和寄存器等胀糜,這些在上下文切換時(shí)也是需要保存的颅拦。
所以線程上下文切換包括了 2 種情況:
不同進(jìn)程的線程,這種情況等同于進(jìn)程切換教藻。
通進(jìn)程的線程切換距帅,只需要切換線程私有數(shù)據(jù)、寄存器等不共享數(shù)據(jù)括堤。
中斷上下文切換
中斷處理會(huì)打斷進(jìn)程的正常調(diào)度和執(zhí)行锥债,轉(zhuǎn)而調(diào)用中斷處理程序,響應(yīng)設(shè)備事件痊臭。而在打斷其他進(jìn)程時(shí),就需要將進(jìn)程當(dāng)前的狀態(tài)保存下來登夫,這樣在中斷結(jié)束后广匙,進(jìn)程仍然可以從原來的狀態(tài)恢復(fù)運(yùn)行。
對(duì)同一個(gè) CPU 來說恼策,中斷處理比進(jìn)程擁有更高的優(yōu)先級(jí)鸦致,所以中斷上下文切換并不會(huì)與進(jìn)程上下文切換同時(shí)發(fā)生。由于中斷會(huì)打斷正常進(jìn)程的調(diào)度和執(zhí)行涣楷,所以大部分中斷處理程序都短小精悍分唾,以便盡可能快的執(zhí)行結(jié)束。
查看系統(tǒng)上下文切換
vmstat:工具可以查看系統(tǒng)的內(nèi)存狮斗、CPU 上下文切換以及中斷次數(shù):
// 每隔1秒輸出
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r? b? swpd? free? buff? cache? si? so? ? bi? ? bo? in? cs us sy id wa st
3? 0? ? ? 0 157256 3241604 5144444? ? 0? ? 0? ? 20? ? 0 26503 33960 18? 7 75? 0? 0
17? 0? ? ? 0 159984 3241708 5144452? ? 0? ? 0? ? 12? ? 0 29560 37696 15 10 75? 0? 0
6? 0? ? ? 0 162044 3241816 5144456? ? 0? ? 0? ? 8? 120 30683 38861 17 10 73? 0? 0
cs:則為每秒的上下文切換次數(shù)绽乔。
in:則為每秒的中斷次數(shù)。
r:就緒隊(duì)列長度碳褒,正在運(yùn)行或等待 CPU 的進(jìn)程折砸。
b:不可中斷睡眠狀態(tài)的進(jìn)程數(shù),例如正在和硬件交互沙峻。
pidstat:使用pidstat -w選項(xiàng)查看具體進(jìn)程的上下文切換次數(shù):
$ pidstat -w -p 3217281 1
10:19:13? ? ? UID? ? ? PID? cswch/s nvcswch/s? Command
10:19:14? ? ? ? 0? 3217281? ? ? 0.00? ? 18.00? stress
10:19:15? ? ? ? 0? 3217281? ? ? 0.00? ? 18.00? stress
10:19:16? ? ? ? 0? 3217281? ? ? 0.00? ? 28.71? stress
其中cswch/s和nvcswch/s表示自愿上下文切換和非自愿上下文切換睦授。
自愿上下文切換:是指進(jìn)程無法獲取所需資源,導(dǎo)致的上下文切換摔寨。比如說去枷, I/O、內(nèi)存等系統(tǒng)資源不足時(shí),就會(huì)發(fā)生自愿上下文切換删顶。
非自愿上下文切換:則是指進(jìn)程由于時(shí)間片已到等原因竖螃,被系統(tǒng)強(qiáng)制調(diào)度,進(jìn)而發(fā)生的上下文切換翼闹。比如說斑鼻,大量進(jìn)程都在爭搶 CPU 時(shí),就容易發(fā)生非自愿上下文切換
案例問題排查
這里我們使用sysbench工具模擬上下文切換問題猎荠。
先使用vmstat 1查看當(dāng)前上下文切換信息:
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r? b? swpd? free? buff? cache? si? so? ? bi? ? bo? in? cs us sy id wa st
2? 0? ? ? 0 514540 3364828 5323356? ? 0? ? 0? ? 10? ? 16? ? 0? ? 0? 4? 1 95? 0? 0
1? 0? ? ? 0 514316 3364932 5323408? ? 0? ? 0? ? 8? ? 0 27900 34809 17 10 73? 0? 0
1? 0? ? ? 0 507036 3365008 5323500? ? 0? ? 0? ? 8? ? 0 23750 30058 19? 9 72? 0? 0
然后使用sysbench --threads=64 --max-time=300 threads run模擬 64 個(gè)線程執(zhí)行任務(wù)坚弱,此時(shí)我們?cè)俅蝪mstat 1查看上下文切換信息:
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r? b? swpd? free? buff? cache? si? so? ? bi? ? bo? in? cs us sy id wa st
2? 0? ? ? 0 318792 3385728 5474272? ? 0? ? 0? ? 10? ? 16? ? 0? ? 0? 4? 1 95? 0? 0
1? 0? ? ? 0 307492 3385756 5474316? ? 0? ? 0? ? 8? ? 0 15710 20569 20? 8 72? 0? 0
1? 0? ? ? 0 330032 3385824 5474376? ? 0? ? 0? ? 8? ? 16 21573 26844 19? 9 72? 0? 0
2? 0? ? ? 0 321264 3385876 5474396? ? 0? ? 0? ? 12? ? 0 21218 26100 20? 7 73? 0? 0
6? 0? ? ? 0 320172 3385932 5474440? ? 0? ? 0? ? 12? ? 0 19363 23969 19? 8 73? 0? 0
14? 0? ? ? 0 323488 3385980 5474828? ? 0? ? 0? ? 64? 788 111647 3745536 24 61 15? 0? 0
14? 0? ? ? 0 323576 3386028 5474856? ? 0? ? 0? ? 8? ? 0 118383 4317546 25 64 11? 0? 0
16? 0? ? ? 0 315560 3386100 5475056? ? 0? ? 0? ? 8? ? 16 115253 4553099 22 68? 9? 0? 0
我們可以明顯的觀察到:
當(dāng)前 cs、in 此時(shí)劇增关摇。
sy+us 的 CPU 占用超過 90%荒叶。
r 就緒隊(duì)列長度達(dá)到 16 個(gè)超過了 CPU 核心數(shù) 8 個(gè)。
分析 cs 上下文切換問題
我們使用pidstat查看當(dāng)前 CPU 信息和具體的進(jìn)程上下文切換信息:
// -w表示查看進(jìn)程切換信息输虱,-u查看CPU信息些楣,-t查看線程切換信息
$ pidstat -w -u -t 1
10:35:01? ? ? UID? ? ? PID? ? %usr %system? %guest? ? %CPU? CPU? Command
10:35:02? ? ? ? 0? 3383478? 67.33? 100.00? ? 0.00? 100.00? ? 1? sysbench
10:35:01? ? ? UID? ? ? PID? cswch/s nvcswch/s? Command
10:45:39? ? ? ? 0? 3509357? ? ? ? -? ? ? 1.00? ? ? 0.00? kworker/2:2
10:45:39? ? ? ? 0? ? ? ? -? 3509357? ? ? 1.00? ? ? 0.00? |__kworker/2:2
10:45:39? ? ? ? 0? ? ? ? -? 3509702? 38478.00? 45587.00? |__sysbench
10:45:39? ? ? ? 0? ? ? ? -? 3509703? 39913.00? 41565.00? |__sysbench
所以我們可以看到大量的sysbench線程存在很多的上下文切換。
分析 in 中斷問題
我們可以查看系統(tǒng)的watch -d cat /proc/softirqs以及watch -d cat /proc/interrupts來查看系統(tǒng)的軟中斷和硬中斷(內(nèi)核中斷)宪睹。我們這里主要觀察/proc/interrupts即可愁茁。
$ watch -d cat /proc/interrupts
RES:? 900997016? 912023527? 904378994? 902594579? 899800739? 897500263? 895024925? 895452133? Rescheduling interrupts
這里明顯看出重調(diào)度中斷(RES)增多,這個(gè)中斷表示喚醒空閑狀態(tài) CPU 來調(diào)度新任務(wù)執(zhí)行亭病,
總結(jié)
自愿上下文切換變多了鹅很,說明進(jìn)程都在等待資源,有可能發(fā)生了 I/O 等其他問題罪帖。
非自愿上下文切換變多了促煮,說明進(jìn)程都在被強(qiáng)制調(diào)度,也就是都在爭搶 CPU整袁,說明 CPU 的確成了瓶頸菠齿。
中斷次數(shù)變多了,說明 CPU 被中斷處理程序占用坐昙,還需要通過查看/proc/interrupts文件來分析具體的中斷類型绳匀。
CPU 使用率
除了系統(tǒng)負(fù)載、上下文切換信息民珍,最直觀的 CPU 問題指標(biāo)就是 CPU 使用率信息襟士。Linux 通過/proc虛擬文件系統(tǒng)向用戶控件提供系統(tǒng)內(nèi)部狀態(tài)信息,其中/proc/stat則是 CPU 和任務(wù)信息統(tǒng)計(jì)嚷量。
$ cat /proc/stat | grep cpu
cpu? 6392076667 1160 3371352191 52468445328 3266914 37086 36028236 20721765 0 0
cpu0 889532957 175 493755012 6424323330 2180394 37079 17095455 3852990 0 0
...
這里每一列的含義如下:
user(通陈穑縮寫為 us),代表用戶態(tài) CPU 時(shí)間蝶溶。注意嗜历,它不包括下面的 nice 時(shí)間宣渗,但包括了 guest 時(shí)間。
nice(通忱嬷荩縮寫為 ni)痕囱,代表低優(yōu)先級(jí)用戶態(tài) CPU 時(shí)間,也就是進(jìn)程的 nice 值被調(diào)整為 1-19 之間時(shí)的 CPU 時(shí)間暴匠。這里注意鞍恢,nice 可取值范圍是 -20 到 19,數(shù)值越大每窖,優(yōu)先級(jí)反而越低帮掉。
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)致讥,代表通過虛擬化運(yùn)行其他操作系統(tǒng)的時(shí)間,也就是運(yùn)行虛擬機(jī)的 CPU 時(shí)間器赞。
guest_nice(通彻父ぃ縮寫為 gnice),代表以低優(yōu)先級(jí)運(yùn)行虛擬機(jī)的時(shí)間港柜。
這里我們可以使用top请契、ps咳榜、pidstat等工具方便的查詢這些數(shù)據(jù),可以很方便的看到 CPU 使用率很高的進(jìn)程爽锥,這里我們可以通過這些工具初步定為涌韩,但是具體的問題原因還需要其他方法繼續(xù)查找。
這里我們可以使用perf top方便查看熱點(diǎn)數(shù)據(jù)氯夷,也可以使用perf record可以將當(dāng)前數(shù)據(jù)保存起來方便后續(xù)使用perf report查看臣樱。
CPU 使用率問題排查
這里總結(jié)一下 CPU 使用率問題及排查思路:
用戶 CPU 和 Nice CPU 高,說明用戶態(tài)進(jìn)程占用了較多的 CPU腮考,所以應(yīng)該著重排查進(jìn)程的性能問題雇毫。
系統(tǒng) CPU 高,說明內(nèi)核態(tài)占用了較多的 CPU秸仙,所以應(yīng)該著重排查內(nèi)核線程或者系統(tǒng)調(diào)用的性能問題嘴拢。
I/O 等待 CPU 高,說明等待 I/O 的時(shí)間比較長寂纪,所以應(yīng)該著重排查系統(tǒng)存儲(chǔ)是不是出現(xiàn)了 I/O 問題席吴。
軟中斷和硬中斷高,說明軟中斷或硬中斷的處理程序占用了較多的 CPU捞蛋,所以應(yīng)該著重排查內(nèi)核中的中斷服務(wù)程序孝冒。
CPU 問題排查套路
CPU 使用率
CPU 使用率主要包含以下幾個(gè)方面:
用戶 CPU 使用率,包括用戶態(tài) CPU 使用率(user)和低優(yōu)先級(jí)用戶態(tài) CPU 使用率(nice)拟杉,表示 CPU 在用戶態(tài)運(yùn)行的時(shí)間百分比庄涡。用戶 CPU 使用率高,通常說明有應(yīng)用程序比較繁忙搬设。
系統(tǒng) CPU 使用率穴店,表示 CPU 在內(nèi)核態(tài)運(yùn)行的時(shí)間百分比(不包括中斷)。系統(tǒng) CPU 使用率高拿穴,說明內(nèi)核比較繁忙泣洞。
等待 I/O 的 CPU 使用率,通常也稱為 iowait默色,表示等待 I/O 的時(shí)間百分比球凰。iowait 高,通常說明系統(tǒng)與硬件設(shè)備的 I/O 交互時(shí)間比較長腿宰。
軟中斷和硬中斷的 CPU 使用率呕诉,分別表示內(nèi)核調(diào)用軟中斷處理程序、硬中斷處理程序的時(shí)間百分比吃度。它們的使用率高甩挫,通常說明系統(tǒng)發(fā)生了大量的中斷。
除在虛擬化環(huán)境中會(huì)用到的竊取 CPU 使用率(steal)和客戶 CPU 使用率(guest)椿每,分別表示被其他虛擬機(jī)占用的 CPU 時(shí)間百分比捶闸,和運(yùn)行客戶虛擬機(jī)的 CPU 時(shí)間百分比夜畴。
平均負(fù)載
反應(yīng)了系統(tǒng)的整體負(fù)載情況,可以查看過去 1 分鐘删壮、過去 5 分鐘和過去 15 分鐘的平均負(fù)載贪绘。
上下文切換
上下文切換主要關(guān)注 2 項(xiàng)指標(biāo):
無法獲取資源而導(dǎo)致的自愿上下文切換。
被系統(tǒng)強(qiáng)制調(diào)度導(dǎo)致的非自愿上下文切換央碟。
CPU 緩存命中率
CPU 的訪問速度遠(yuǎn)大于內(nèi)存訪問税灌,這樣在 CPU 訪問內(nèi)存時(shí)不可避免的要等待內(nèi)存響應(yīng)。為了協(xié)調(diào) 2 者的速度差距出現(xiàn)了 CPU 緩存(多級(jí)緩存)亿虽。如果 CPU 緩存命中率越高則性能會(huì)更好菱涤,我們可以使用以下工具查看 CPU 緩存命中率,工具地址洛勉、項(xiàng)目地址 perf-tools
# ./cachestat -t
Counting cache functions... Output every 1 seconds.
TIME? ? ? ? HITS? MISSES? DIRTIES? ? RATIO? BUFFERS_MB? CACHE_MB
08:28:57? ? ? 415? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 1? ? ? ? 191
08:28:58? ? ? 411? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 1? ? ? ? 191
08:28:59? ? ? 362? ? ? 97? ? ? ? 0? ? 78.9%? ? ? ? ? ? 0? ? ? ? ? 8
08:29:00? ? ? 411? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? ? 9
08:29:01? ? ? 775? ? 20489? ? ? ? 0? ? 3.6%? ? ? ? ? ? 0? ? ? ? 89
08:29:02? ? ? 411? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? 89
08:29:03? ? 6069? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? 89
08:29:04? ? 15249? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? 89
08:29:05? ? ? 411? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? 89
08:29:06? ? ? 411? ? ? ? 0? ? ? ? 0? 100.0%? ? ? ? ? ? 0? ? ? ? 89
08:29:07? ? ? 411? ? ? ? 0? ? ? ? 3? 100.0%? ? ? ? ? ? 0? ? ? ? 89
[...]
總結(jié)
通過性能指標(biāo)查工具(CPU 相關(guān))
性能指標(biāo) 工具 說明
平均負(fù)載 uptime
top uptime 簡單展示最近一段時(shí)間的平均負(fù)載
top 展示更多指標(biāo)
CPU 使用率 vmstat
mpstat
top
sar
/proc/stat
top粘秆、vmstat、mpstat 只可以動(dòng)態(tài)查看當(dāng)前收毫,而 sar 可以查看歷史
/proc/stat 是其他性能工具的數(shù)據(jù)來源
進(jìn)程 CPU 使用率 top
pidstat
ps
htop
atop
top攻走、ps 可以以排序方式展示進(jìn)程 CPU、pidstat 不可排序展示
htop此再、atop 則以不同顏色展示各類數(shù)據(jù)更直觀
系統(tǒng)上下文切換 vmstat 展示上下文切換此時(shí)昔搂、運(yùn)行狀態(tài)、不可中斷狀態(tài)進(jìn)程數(shù)量
進(jìn)程上下文切換 pidstat 展示項(xiàng)很多输拇,包括進(jìn)程上下文切換信息
軟中斷 top
/proc/softirqs
mpstat top 可查看軟中斷 CPU 使用率
/proc/softirqs 和 mpstat 則可以查看每個(gè) CPU 上的累計(jì)信息
硬中斷 vmstat
/proc/interrupts vmstat 查看總中斷次數(shù)信息
/proc/interrupts 查看各種中斷在每個(gè) CPU 核心上的累計(jì)信息
網(wǎng)絡(luò) dstat
sar
tcpdump dstat摘符、sar 較詳細(xì)的展示出總的網(wǎng)絡(luò)收發(fā)情況
tcpdump 提供動(dòng)態(tài)抓取數(shù)據(jù)包的能力
IO dstat、sar 2 者都提供了詳細(xì)的 IO 整體情況
CPU 信息 /proc/cpuinfo
lscpu 都可以查看 CPU 信息
系統(tǒng)分析 perf
execsnoop perf 分析各種內(nèi)核函數(shù)調(diào)用策吠、熱點(diǎn)函數(shù)信息
execsnoop 監(jiān)控短時(shí)進(jìn)程
根據(jù)工具查性能指標(biāo)(CPU 相關(guān))
性能工具 CPU 性能指標(biāo)
uptime 5逛裤、10、15 分鐘內(nèi)的平均負(fù)載展示
top 平均負(fù)載猴抹、運(yùn)行隊(duì)列别凹、CPU 各項(xiàng)使用率、進(jìn)程狀態(tài)和 CPU 使用率
htop top 增強(qiáng)版洽糟,以不同顏色區(qū)分不同類型進(jìn)程,展示更直觀
atop CPU堕战、內(nèi)存坤溃、磁盤、網(wǎng)絡(luò)資源全訪問監(jiān)控嘱丢,十分齊全
vmstat 系統(tǒng)整體 CPU 使用率薪介、上下文切換次數(shù)、中斷次數(shù)越驻,還包括處于運(yùn)行(r)和不可中斷狀態(tài)(b)的進(jìn)程數(shù)量
pidstat 進(jìn)程汁政、線程(-t)的每個(gè) CPU 占用信息道偷,中斷上下文切換次數(shù)
/proc/softirqs 展示每個(gè) CPU 上的軟中斷類型及次數(shù)
/proc/inerrupts 展示每個(gè) CPU 上的硬中斷類型及次數(shù)
ps 每個(gè)進(jìn)程的狀態(tài)和 CPU 使用率
pstree 進(jìn)程的父子關(guān)系展示
dstat 系統(tǒng)整體 CPU 使用率(以及相關(guān) IO、網(wǎng)絡(luò)信息)
sar 系統(tǒng)整體 CPU 使用率记劈,以及使用率歷史信息
strace 跟蹤進(jìn)程的系統(tǒng)調(diào)用
perf CPU 性能事件分析勺鸦,例如:函數(shù)調(diào)用鏈、CPU 緩存命中率目木、CPU 調(diào)度等
execsnoop 短時(shí)進(jìn)程分析
CPU 問題排查方向
有了以上性能工具换途,在實(shí)際遇到問題時(shí)我們并不可能全部性能工具跑一遍,這樣效率也太低了刽射,所以這里可以先運(yùn)行幾個(gè)常用的工具 top军拟、vmstat、pidstat 分析系統(tǒng)大概的運(yùn)行情況然后在具體定位原因誓禁。
top 系統(tǒng)CPU => vmstat 上下文切換次數(shù) => pidstat 非自愿上下文切換次數(shù) => 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
top 用戶CPU => pidstat 用戶CPU => 一般是CPU計(jì)算型任務(wù)
top 僵尸進(jìn)程 =>? 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
top 平均負(fù)載 => vmstat 運(yùn)行狀態(tài)進(jìn)程數(shù) =>? pidstat 用戶CPU => 各類進(jìn)程分析工具(perf strace ps execsnoop pstack)
top 等待IO CPU => vmstat 不可中斷狀態(tài)進(jìn)程數(shù)? => IO分析工具(dstat懈息、sar -d)
top 硬中斷 => vmstat 中斷次數(shù) => 查看具體中斷類型(/proc/interrupts)
top 軟中斷 => 查看具體中斷類型(/proc/softirqs) => 網(wǎng)絡(luò)分析工具(sar -n、tcpdump) 或者 SCHED(pidstat 非自愿上下文切換)
CPU 問題優(yōu)化方向
性能優(yōu)化往往是多方面的摹恰,CPU辫继、內(nèi)存、網(wǎng)絡(luò)等都是有關(guān)聯(lián)的戒祠,這里暫且給出 CPU 優(yōu)化的思路骇两,以供參考。
程序優(yōu)化
基本優(yōu)化:程序邏輯的優(yōu)化比如減少循環(huán)次數(shù)姜盈、減少內(nèi)存分配低千,減少遞歸等等。
編譯器優(yōu)化:開啟編譯器優(yōu)化選項(xiàng)例如gcc -O2對(duì)程序代碼優(yōu)化馏颂。
算法優(yōu)化:降低蘇研發(fā)復(fù)雜度示血,例如使用nlogn的排序算法,使用logn的查找算法等救拉。
異步處理:例如把輪詢改為通知方式
多線程代替多進(jìn)程:某些場(chǎng)景下多線程可以代替多進(jìn)程难审,因?yàn)樯舷挛那袚Q成本較低
緩存:包括多級(jí)緩存的使用(略)加快數(shù)據(jù)訪問
系統(tǒng)優(yōu)化
CPU 綁定:綁定到一個(gè)或多個(gè) CPU 上,可以提高 CPU 緩存命中率亿絮,減少跨 CPU 調(diào)度帶來的上下文切換問題
CPU 獨(dú)占:跟 CPU 綁定類似告喊,進(jìn)一步將 CPU 分組,并通過 CPU 親和性機(jī)制為其分配進(jìn)程派昧。
優(yōu)先級(jí)調(diào)整:使用 nice 調(diào)整進(jìn)程的優(yōu)先級(jí)黔姜,適當(dāng)降低非核心應(yīng)用的優(yōu)先級(jí),增高核心應(yīng)用的優(yōu)先級(jí)蒂萎,可以確保核心應(yīng)用得到優(yōu)先處理秆吵。
為進(jìn)程設(shè)置資源限制:使用 Linux cgroups 來設(shè)置進(jìn)程的 CPU 使用上限,可以防止由于某個(gè)應(yīng)用自身的問題五慈,而耗盡系統(tǒng)資源纳寂。
NUMA 優(yōu)化:支持 NUMA 的處理器會(huì)被劃分為多個(gè) Node主穗,每個(gè) Node 有本地的內(nèi)存空間,這樣 CPU 可以直接訪問本地空間內(nèi)存毙芜。
中斷負(fù)載均衡:無論是軟中斷還是硬中斷忽媒,它們的中斷處理程序都可能會(huì)耗費(fèi)大量的 CPU。開啟 irqbalance 服務(wù)或者配置 smp_affinity爷肝,就可以把中斷處理過程自動(dòng)負(fù)載均衡到多個(gè) CPU 上猾浦。