博客 / 詳情

返回

linux性能分析篇之cpu、io

1. 工具介紹

vmstat

選用vmstat原因:大多數的發行版基本都有此命令,但是procinfo,pidstat,mpstat等命令是沒有的。

[root@cubblestone ~]# vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 500488 153152 1139216 0 0 1 215 3 3 1 1 98 1 0
0 0 0 500488 153152 1139220 0 0 0 128 761 1290 0 1 99 0 0
0 0 0 500504 153152 1139220 0 0 0 0 693 1206 0 0 100 0 0
  1. procs
    r 當前可運行的進程數。也就是已經加入了運行隊列,即已經分配了CPU,但是並沒有在等待IO。(所以數量超過了cpu的個數,那麼cpu會有瓶頸)
    b 等待IO完成的被阻塞的進程數。
  2. memory
    swpd 虛擬內存已使用的大小,表示當前已使用的交換頁面大小。如果該值較高,表示系統當前的物理內存不足,導致系統頻繁進行頁面交換。這可能會導致系統性能下降,因為磁盤操作相對於內存訪問速度較慢。
    free 未被OS或者程序使用的物理內存。
    buff 字段表示當前已分配給緩衝的大小(單位KB)。較高的 buff 值通常是好的,因為它表示系統正在有效地使用緩衝區來提高文件系統的性能。當系統需要讀取或寫入文件時,可以從緩衝中獲取數據,而無需直接訪問磁盤,從而加快訪問速度。
    cache 用於保存之前從硬盤讀取的數據的系統告訴緩存或者內存大小(單位KB)。如果應用程序再次需要該數據,內核可以從內存而非硬盤抓取數據,提高性能。
  3. swap
    si 每秒從磁盤讀入虛擬內存的大小(單位KB/s),如果這個值大於0,表示物理內存不夠用或者內存泄露了,要查找耗內存進程解決掉。
    so 每秒虛擬內存寫入磁盤的大小(單位KB/s),如果這個值大於0,同上。
    注:swap被我關掉了,所以si和so為0。
  4. io
    bi Blocks received from a block device (blocks/s), 每秒從塊設備接收到的塊數,單位:塊/秒 也就是讀磁盤。
    bo Blocks sent to a block device (blocks/s), 每秒發送到塊設備的塊數,單位:塊/秒 也就是寫磁盤。
  5. system
    in 每秒CPU的中斷次數,包括時間中斷
    cs 每秒上下文切換次數,例如我們調用系統函數,就要進行上下文切換,線程的切換,也要進程上下文切換,這個值要越小越好,太大了,要考慮調低線程或者進程的數目。
  6. cpu
    us 用户CPU時間。
    sy 系統CPU時間。
    id 空閒 CPU時間,一般來説,id + us + sy = 100。
    wa 等待IO CPU時間。

2. 做實驗

2.1 起一個進程

本次實驗,起一個dd進程,往磁盤寫數據,為防止磁盤滿,寫個while循環清空磁盤。

[root@cubblestone ~]# dd if=/dev/zero of=/opt/file.txt bs=1M count=10000000000 &
[1] 23032
[root@cubblestone ~]#
[root@cubblestone ~]# while true;do sleep 1; echo "" >/opt/file.txt ;done &
[1] 22536
[root@cubblestone ~]#

2.2 持續觀察vmstat輸出結果(命令是每隔1秒輸出一次,並且持續輸出的,分析部分內容即可)

[root@cubblestone ~]# 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
 4  0      0 1091492  20292 675056    0    0     1   219    3    3  1  1 98  1  0
 0  1      0 1248084  20292 517664    0    0     0 154728 1444 1980  1 16 18 66  0
 1  1      0 962176  20292 803552    0    0     0 174600 2266 2548  1 18 41 41  0
 1  1      0 1274380  20292 491332    0    0     0 105992 1647 2322  0 11 18 71  0
 0  2      0 925148  20304 841484    0    0     0 199836 2035 2364  1 18 33 48  0
 0  1      0 1299008  20304 466952    0    0     0 80912 2554 7343  1 10 25 64  0
 0  2      0 893668  20304 871752    0    0     0 225740 2150 2759  2 21 31 47  0
 2  3      0 1324848  20304 439260    0    0     0 52832 2165 2765  1 13 17 70  0
 0  2      0 861524  20400 904692    0    0     0 255576 2125 3304  1 21 21 57  0
 1  0      0 1269596  20400 496764    0    0     0 23092 2235 2744  0 14 40 46  0
 1  0      0 1074792  20400 691200    0    0     0 273936 1479 1950  1 23 24 53  0
 1  1      0 983796  20404 780544    0    0    20 160248 2575 3037  3 22 42 34  0
 0  1      0 1256388  20404 507432    0    0     0 121380 2185 5755  1 11 16 72  0
 2  1      0 941968  20412 822788    0    0     0 180944 2064 2348  1 16 35 48  0
 0  1      0 1285236  20412 478680    0    0     0 97804 1873 4189  1  9 26 64  0
 0  2      0 905644  20412 858736    0    0     0 215472 1979 2225  1 18 35 46  0
 0  1      0 1309372  20412 454588    0    0     0 68196 2231 4951  1 10 31 57  0
 0  3      0 875620  20412 888492    0    0     0 239008 2422 3655  1 19 26 54  0
 0  5      0 1335960  20412 428052    0    0     0 41620 2186 2654  1  7 24 68  0
 0  2      0 848184  20516 916284    0    0     0 262316 2038 2771  3 20 14 63  0
 1  0      0 1236948  20516 527692    0    0     0 23112 2313 2608  1 11 45 44  0
 1  0      0 1146916  20516 616888    0    0     0 279528 1967 3978  1 21 15 64  0
 1  1      0 993188  20516 772152    0    0     0 157652 3020 3914  1 18 45 36  0
 0  1      0 1261300  20516 503236    0    0     0 118852 1549 2300  1 14 14 71  0

IO和CPU分析

讓我們來關注下相關字段bi、bo、in、cs、us、sy、id、wa。

  1. 從bi、bo字段,我們可以看出,由進程在瘋狂向磁盤寫數據,而沒什麼讀數據的動作。忽略第一行,寫的速率在大概在80000(塊/秒)~ 260000(塊/秒),我的磁盤為/dev/vda1,所以塊的大小如下

    [root@cubblestone ~]# tune2fs -l /dev/vda1 | grep "Block size"
    Block size:               4096
    [root@cubblestone ~]#
  2. 4096字節也就是2KB。那麼也就能計算出寫速率了,大概在156(MB/s) ~ 508(MB/s)。所以為什麼能看出有進程在瘋狂的寫數據。
  3. 結合b字段可以看出,時不時有數個進程在等待IO完成。
  4. 再結合CPU部分,us和sy都比較小,代表用户態和內核態消耗的CPU不大,而wa的佔比很高(在30%~70%),代表CPU消耗在IO上的時間很長,也能説明有進程在瘋狂IO。(注:us+sy+id+wa+st = 100)
    但是這樣並不能説明進程就達到了瓶頸,萬一人家磁盤就是好,能夠支持的寫速率就是很高呢,讓我們來想看下磁盤情況。

iostat

需要安裝iostat

yum install sysstat -y

命令説明:1秒鐘輸出一次結果,輸出3次。(分析真正的結果需要忽略第一次的輸出,命令特性,vmstat也一樣。)

[root@cubblestone yum.repos.d]# iostat -x 1 3
Linux 3.10.0-1160.71.1.el7.x86_64 (cubblestone)         06/04/2023      _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.83    0.00    0.77    0.58    0.00   97.81

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     8.17    0.05    9.28     1.60   486.01   104.52     0.72   77.28   19.63   77.60   1.25   1.16
scd0              0.00     0.00    0.00    0.00     0.10     0.00   120.62     0.00    0.51    0.51    0.00   0.42   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00   18.69   37.37    0.00   43.94

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     4.00    0.00  326.00     0.00 109648.00   672.69   174.38  534.91    0.00  534.91   2.58  84.20
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.52    0.00    7.73   63.92    0.00   27.84

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.00    0.00  231.00     0.00 110028.00   952.62   155.38  672.66    0.00  672.66   4.33 100.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

[root@cubblestone yum.repos.d]#

命令字段解釋
avg-cpu 行:統計了CPU的平均使用率,可以看出iowait達到了30~60,跟vmstat的wa字段是一個意思。
下面才是分析磁盤的字段。

  • rrqm/s 在提交給磁盤前,每秒被合併的讀請求的數量。
  • wrqm/s 在提交給磁盤前,每秒被合併的寫請求的數量。
  • r/s 每秒讀取的io次數。
  • w/s 每秒寫入的io次數。
  • rMB/s 表示每秒讀取的數據量,單位為MB。
  • wMB/s 表示每秒寫入的數據量,單位為MB。
  • avgrq-sz 表示平均每個I/O請求的扇區數,單位為扇區。
  • avgqu-sz 表示平均每個設備隊列中的請求數量,單位為請求數量。
  • await 表示請求的平均消耗的時間,單位為毫秒。
  • r_await 表示讀請求的平均等待時間,單位為毫秒。
  • w_await 表示寫請求的平均等待時間,單位為毫秒。
  • svctm 表示平均每個I/O請求的服務時間,單位為毫秒。
  • %util 表示設備的利用率百分比,沒有具體的單位。

想看有沒瓶頸,着重關注如下幾個字段
await r_await w_await svctm
await:其代表的是IO請求,從加入IO隊列開始到其真正處理完數據,平均消耗的時間,也就是【等待+處理】的時間。
r_await、w_await:跟await含義一樣,只是從await中拆分出來讀和寫的情況。
svctm: 表示的是IO請求從開始處理到處理完畢消耗的平均時間,也就是【處理】的時間。

以上面的命令最後一次輸出的結果為例:
vda磁盤的await達到了672.66ms,而svctm只有4.33ms,從他倆的差距可以看出,時間都耗在了等待IO上面。

那是什麼進程在產生大量的IO呢?

iotop

[root@cubblestone ~]# iotop -oP

由下圖顯而易見:
WX20230604-212130@2x.png

總結

從上面的vmstat到下面的iostat我們可以得出如下結論:

vmstat可以看到有產生大量IO的進程,IO佔用CPU在30%~70%,然後我們排查是哪個磁盤在進行IO。

iostat可以看出是vda在進行大量的IO,並且await已經遠遠大於svctm,所以IO達到了瓶頸。
然後通過iotop排查出是我們的dd進程在瘋狂寫數據到vda磁盤。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.