?Linux CPU 性能優(yōu)化指南

系統(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 上猾浦。

https://blog.csdn.net/Tencent_TEG/article/details/107925196

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市灯抛,隨后出現(xiàn)的幾起案子姿锭,更是在濱河造成了極大的恐慌奸汇,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異邑茄,居然都是意外死亡甘萧,警方通過查閱死者的電腦和手機(jī)肩杈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門腔剂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人靡砌,你說我怎么就攤上這事已脓。” “怎么了通殃?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵度液,是天一觀的道長。 經(jīng)常有香客問我画舌,道長堕担,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任曲聂,我火速辦了婚禮霹购,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朋腋。我一直安慰自己齐疙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布旭咽。 她就那樣靜靜地躺著贞奋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轻专。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天察蹲,我揣著相機(jī)與錄音请垛,去河邊找鬼催训。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宗收,可吹牛的內(nèi)容都是我干的漫拭。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼混稽,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼采驻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起匈勋,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤礼旅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后洽洁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痘系,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年饿自,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汰翠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昭雌,死狀恐怖复唤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烛卧,我是刑警寧澤佛纫,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站唱星,受9級(jí)特大地震影響雳旅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜间聊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一攒盈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哎榴,春花似錦型豁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至飘言,卻和暖如春衣形,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工谆吴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倒源,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓句狼,卻偏偏與公主長得像笋熬,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腻菇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361