當遇到 I/O 性能問題時读存,可以使用 iostat为流、iotop、 blktrace 等工具分析磁盤 I/O 的瓶頸让簿。
查看/proc/<pid>/下的的meminfo艺谆、status等文件可以具體才看到虛擬內(nèi)存和實際物理內(nèi)存 的使用情況。
查看cpu個數(shù):grep 'model name' /proc/cpuinfo | wc -l
使用 uptime 命令查看三個不同時間間隔的平均值拜英,如果 1 分鐘、5 分鐘琅催、15 分鐘的三個值基本相同居凶,或者相差不大,那就說明系統(tǒng)負載很平穩(wěn)藤抡。
案例
基于 Ubuntu 18.04侠碧,預(yù)先安裝 stress 和 sysstat 包
apt install stress sysstat
sudo apt install stress
場景一:CPU 密集型進程
運行 stress 命令,模擬一個 CPU 使用率 100% 的場景:
在一個終端執(zhí)行:stress --cpu 1 --timeout 600
在另一個終端執(zhí)行:watch -d uptime
在第三個終端運行 mpstat 查看 CPU 使用率的變化情況:
# -P ALL 表示監(jiān)控所有 CPU缠黍,后面數(shù)字 5 表示間隔 5 秒后輸出一組數(shù)據(jù)
root@davinci-mini:/home/HwHiAiUser# mpstat -P ALL 5
Linux 4.19.90+ (davinci-mini) 12/23/21 _aarch64_ (8 CPU)
18:28:02 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
18:28:07 all 13.48 0.00 3.14 0.05 0.00 0.05 0.00 0.00 0.00 83.27
18:28:07 0 19.18 0.00 2.45 0.00 0.00 0.20 0.00 0.00 0.00 78.16
18:28:07 1 18.53 0.00 3.67 0.00 0.00 0.00 0.00 0.00 0.00 77.80
18:28:07 2 20.69 0.00 5.07 0.00 0.00 0.00 0.00 0.00 0.00 74.24
18:28:07 3 19.31 0.00 4.88 0.00 0.00 0.00 0.00 0.00 0.00 75.81
18:28:07 4 15.31 0.00 4.29 0.00 0.00 0.20 0.00 0.00 0.00 80.20
18:28:07 5 15.27 0.00 4.68 0.41 0.00 0.20 0.00 0.00 0.00 79.43
18:28:07 6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
18:28:07 7 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
查看哪個進程導(dǎo)致了 CPU 使用率高弄兜,可以使用 pidstat 來查詢:
# 間隔 5 秒后輸出一組數(shù)據(jù)
root@davinci-mini:/home/HwHiAiUser# pidstat -u 5 1
Linux 4.19.90+ (davinci-mini) 12/23/21 _aarch64_ (8 CPU)
18:30:20 UID PID %usr %system %guest %wait %CPU CPU Command
18:30:25 0 10 0.00 0.20 0.00 0.00 0.20 3 rcu_sched
18:30:25 0 1007 0.20 0.00 0.00 0.00 0.20 0 systemd-journal
18:30:25 100 1370 0.00 0.20 0.00 0.00 0.20 0 systemd-network
18:30:25 0 1883 0.00 0.20 0.00 0.00 0.20 2 drvlog_work_0
18:30:25 1000 2207 0.00 0.20 0.00 0.00 0.20 0 dmp_daemon
18:30:25 0 2352 2.59 1.59 0.00 0.00 4.18 5 analyzer
18:30:25 0 2406 0.20 0.00 0.00 0.00 0.20 3 alertmanager
18:30:25 0 2709 0.00 0.20 0.00 0.00 0.20 5 npu-smi
18:30:25 0 8552 0.20 0.40 0.00 0.00 0.60 1 pidstat
18:30:25 0 10352 0.00 0.20 0.00 0.00 0.20 5 kworker/5:1H-kblockd
18:30:25 0 12070 8.37 0.80 0.00 0.00 9.16 2 java
18:30:25 0 14614 0.20 1.20 0.00 0.00 1.39 4 stream
18:30:25 0 24877 0.00 0.20 0.00 0.00 0.20 0 kworker/0:2-events
18:30:25 0 25422 93.43 20.32 0.00 0.00 100.00 3 vmr-lite
場景二:I/O 密集型進程
運行 stress 命令,但這次模擬 I/O 壓力,即不停地執(zhí)行 sync:
在一個終端執(zhí)行:stress -i 1 --timeout 600
在第二個終端運行 uptime 查看平均負載的變化情況:watch -d uptime
第三個終端運行 mpstat 查看 CPU 使用率的變化情況:
# 顯示所有 CPU 的指標替饿,并在間隔 5 秒輸出一組數(shù)據(jù)
mpstat -P ALL 5 1
可以看到iowait導(dǎo)致平均負載升高
哪個進程语泽,導(dǎo)致 iowait 這么高呢?我們還是用 pidstat 來查詢:
# 間隔 5 秒后輸出一組數(shù)據(jù),-u 表示 CPU 指標
pidstat -u 5 1
可以發(fā)現(xiàn)视卢,是 stress 進程導(dǎo)致的踱卵。
場景三:大量進程的場景
當系統(tǒng)中運行進程超出 CPU 運行能力時,就會出現(xiàn)等待 CPU 的進程据过。
我們使用 stress惋砂,但這次模擬的是 8 個進程: stress -c 8 --timeout 600
由于系統(tǒng)只有 2 個 CPU,明顯比 8 個進程要少得多绳锅,因而西饵,系統(tǒng)的 CPU 處于嚴重過載狀態(tài), 平均負載高達 7.97:
uptime
..., load average: 7.97, 5.93, 3.02
接著再運行 pidstat 來看一下進程的情況:
# 間隔 5 秒后輸出一組數(shù)據(jù)鳞芙,-u 表示 CPU 指標
pidstat -u 5 1
8 個進程在爭搶 2 個 CPU眷柔,每個進程等待 CPU 的時間(也就是代碼塊中的 %wait 列)高達 75%。這些超出 CPU 計算能力的進程积蜻,最終導(dǎo)致 CPU 過載闯割。
小結(jié)
平均負載高有可能是 CPU 密集型進程導(dǎo)致的;
平均負載高并不一定代表 CPU 使用率高,還有可能是 I/O 更繁忙了;
當發(fā)現(xiàn)負載高的時候竿拆,你可以使用 mpstat宙拉、pidstat 等工具,輔助分析負載的來源丙笋。
上下文切換導(dǎo)致負載高
vmstat是一個常用的系統(tǒng)性能分析工具谢澈,主要用來分析系統(tǒng)的內(nèi)存使用情況,也常用來分析 CPU 上下文切換和中斷的次數(shù)御板。
HwHiAiUser@davinci-mini:~$ vmstat 5
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 2297856 1048880 1900820 0 0 1 18 2 0 19 4 77 0 0
3 0 0 2344436 1048880 1900856 0 0 0 85 25325 50968 22 5 74 0 0
6 0 0 2424336 1048888 1900860 0 0 0 160 25343 49313 15 4 81 0 0
2 0 0 2433636 1048888 1900868 0 0 0 100 24543 48054 23 4 72 0 0
3 0 0 2437372 1048888 1900880 0 0 0 95 23893 48505 21 4 75 0 0
cs(context switch)是每秒上下文切換的次數(shù)锥忿。
in(interrupt)則是每秒中斷的次數(shù)。
r(Running or Runnable)是就緒隊列的長度怠肋,也就是正在運行和等待 CPU 的進程數(shù)敬鬓。
b(Blocked)則是處于不可中斷睡眠狀態(tài)的進程數(shù)。
vmstat 只給出了系統(tǒng)總體的上下文切換情況笙各,要想查看每個進程的詳細情況钉答,就需要使用我們 前面提到過的 pidstat 了。給它加上 -w 選項杈抢,你就可以查看每個進程上下文切換的情況了数尿。
HwHiAiUser@davinci-mini:~$ pidstat -w 5
Linux 4.19.90+ (davinci-mini) 12/23/21 _aarch64_ (8 CPU)
18:57:58 UID PID cswch/s nvcswch/s Command
18:58:03 0 1 0.20 0.00 systemd
18:58:03 0 9 10.76 0.80 ksoftirqd/0
18:58:03 0 10 113.55 0.00 rcu_sched
18:58:03 0 12 0.40 0.00 migration/0
18:58:03 0 15 0.40 0.00 migration/1
18:58:03 0 16 0.40 0.00 ksoftirqd/1
這個結(jié)果中有兩列內(nèi)容是我們的重點關(guān)注對象。
一個是 cswch 惶楼,表示每秒自愿上下文切換 (voluntary context switches)的次數(shù)右蹦。
另一個則是 nvcswch 诊杆,表示每秒非自愿上下文切換 (non voluntary context switches)的次數(shù)。
案例
使用 sysbench 來模擬系統(tǒng)多線程調(diào)度切換的情況何陆,預(yù)先安裝 sysbench 和 sysstat 包晨汹,如 apt install sysbench sysstat
在第一個終端里運行 sysbench ,模擬系統(tǒng)多線程調(diào)度的瓶頸:
# 以 10 個線程運行 5 分鐘的基準測試甲献,模擬多線程切換的問題
sysbench --threads=10 --max-time=300 threads run
在第二個終端運行 vmstat 宰缤,觀察上下文切換情況:
# 每隔 1 秒輸出 1 組數(shù)據(jù)(需要 Ctrl+C 才結(jié)束)
$ vmstat 1
你應(yīng)該可以發(fā)現(xiàn),cs 列的上下文切換次數(shù)從之前的 35 驟然上升到了 139 萬晃洒。同時慨灭,注意觀察 其他幾個指標:
r 列:就緒隊列的長度已經(jīng)到了 8,遠遠超過了系統(tǒng) CPU 的個數(shù) 2球及,所以肯定會有大量的 CPU 競爭氧骤。
us(user)和 sy(system)列:這兩列的 CPU 使用率加起來上升到了 100%,其中系統(tǒng) CPU 使用率吃引,也就是 sy 列高達 84%筹陵,說明 CPU 主要是被內(nèi)核占用了。
in 列:中斷次數(shù)也上升到了 1 萬左右镊尺,說明中斷處理也是個潛在的問題朦佩。
綜合這幾個指標,我們可以知道庐氮,系統(tǒng)的就緒隊列過長语稠,也就是正在運行和等待 CPU 的進程數(shù)過多,導(dǎo)致了大量的上下文切換弄砍,而上下文切換又導(dǎo)致了系統(tǒng) CPU 的占用率升高仙畦。
那么到底是什么進程導(dǎo)致了這些問題呢?
在第三個終端再用 pidstat 來看一下, CPU 和進程上下文切換的情況:
# -w 參數(shù)表示輸出進程切換指標音婶,而 -u 參數(shù)則表示輸出 CPU 使用指標
# -wt 參數(shù)表示輸出線程的上下文切換指標
HwHiAiUser@davinci-mini:~$ pidstat -w -u 1
Linux 4.19.90+ (davinci-mini) 12/23/21 _aarch64_ (8 CPU)
19:05:01 UID PID %usr %system %guest %wait %CPU CPU Command
19:05:02 0 10 0.00 0.98 0.00 0.00 0.98 1 rcu_sched
19:05:02 0 1483 0.98 0.00 0.00 0.00 0.98 3 prometheus
19:05:02 0 1904 5.88 0.00 0.00 0.00 5.88 1 java
19:05:02 0 2452 1.96 2.94 0.00 0.00 4.90 1 stream
19:05:02 0 21148 82.35 22.55 0.00 0.00 100.00 5 vmr-lite
19:05:02 0 22155 99.02 11.76 0.00 0.00 100.00 1 analyzer
19:05:02 1000 23640 0.98 0.98 0.00 0.00 1.96 3 pidstat
中斷
從 /proc/interrupts 這個只讀文件中讀取慨畸。/proc 實際上是 Linux 的一個虛擬文 件系統(tǒng),用于內(nèi)核空間與用戶空間之間的通信衣式。/proc/interrupts 就是這種通信機制的一部分寸士, 提供了一個只讀的中斷使用情況。
# -d 參數(shù)表示高亮顯示變化的區(qū)域
$ watch -d cat /proc/interrupts
小結(jié):
首先通過uptime查看系統(tǒng)負載碴卧,然后使用mpstat結(jié)合pidstat來初步判斷到底 是cpu計算量大還是進程爭搶過大或者是io過多碉京,接著使用vmstat分析切換次數(shù),以及切換 類型螟深,來進一步判斷到底是io過多導(dǎo)致問題還是進程爭搶激烈導(dǎo)致問題。
# 并發(fā) 10 個請求測試 Nginx 性能烫葬,總共測試 100 個請求
$ ab -c 10 -n 100 http://192.168.0.10:10000/