CPU分析工具

方法論

CPU分析的一般步驟:

  1. 效能監控指標 工具:通過已有指標或者現成的工具進行初步分析和判斷
  2. 使用USE方法進行進一步分析:U:CPU使用率,S:滿載率:E:錯誤
  3. 測量分析
  4. 微基準測試
  5. 靜態效能優化

本文側重對工具的使用介紹。

基礎分析工具

基礎分析主要包含以下工具的使用:uptime、vmstat、mpstat、sar、ps、top、pidstat,time/ptime

1. uptime

通常uptime可以用來檢視系統負載資訊

$ uptime  19:10:52 up 1135 days,  7:37,  1 user,  load average: 87.87, 77.49, 66.99

最後三列分別是1分鐘、5分鐘和15分鐘系統的平均負載。如果數字是依次減小的,說明現在系統負載在升高,如果是依次增大的,則說明系統負載在降低。

在Linux系統中load值的計算包含系統中正在執行的進行(RUNNING)、可以執行的程序(RUNABLE)和處於不可中斷的程序。

2. vmstat

虛擬記憶體分析工具第一列輸出的是可執行程序數,最後幾列輸出的是cpu相關指標,可以用來分析cpu相關的問題,該工具可顯示CPU正式使用率。

$ 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 58  9      0 856644  44052 88905592    0    0  4214  3852    0    0 61  8 26  5  0 60  7      0 973376  44072 88245416    0    0 324648 333560 265446 247480 62 11 23  3  0 58  5      0 1349060  44068 86577808    0    0 289808 257000 270242 276081 55 18 24  3  0 40 24      0 1573068  44080 84997592    0    0 224756 659252 250767 268095 64 13 17  6  0 120 12      0 1636280  44080 83402944    0    0 307740 283888 249253 253964 56 14 22  8  0 37 14      0 867316  44080 81521136    0    0 454760 298512 275080 294816 51 16 24 10  0 52 11      0 2181236  44260 80656688    0    0 445088 560996 298539 249712 56 12 24  9  0 37  6      0 7423208  44260 81312632    0    0 401356 511956 306425 330183 50  9 33  7  0

跟CPU相關的列分析:

  • r:對於Linux系統該欄位表示所有的Runnable Running程序,不包含處於D狀態的程序,如下圖所示
  • us:使用者態(使用者)CPU使用率
  • sy:核心態(系統)CPU使用率
  • id:CPU空閒率
  • wa:CPU等待I/O使用率,當程序阻塞在磁碟IO上時可以用來衡量CPU idle
  • st:在虛擬化環境顯示被其它租戶佔用的CPU使用率

3. mpstat

多CPU統計工具,可以統計每個CPU的使用情況

~# mpstat -P ALL 1 Linux 5.4.0-99-generic (ambariserver-wangshuaihua-02.dev.kwaidc.com)    02/26/22    _x86_64_    (8 CPU) 15:11:56     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle 15:11:57     all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       2    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       3    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       5    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:11:57       7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

命令輸出列說明:

  • CPU:邏輯CPU序號,或者是all
  • %usr:使用者態(使用者)CPU使用率,不包含%nice
  • %nice:帶有nice程序的使用者態CPU使用率
  • %sys:核心態(系統)CPU使用率
  • %iowait:I/O wait
  • %irq:硬中斷CPU使用率
  • %soft:軟中斷CPU使用率
  • %steal:虛擬化環境其它租戶CPU使用率
  • %guest:客戶端虛擬機器使用使用率
  • %gnice:客戶端虛擬機器帶有nice標記的程序CPU使用率
  • %idle:CPU剩餘率

需要關注的列是 %usr,%sys和%idle,注意檢視每個CPU的使用率,看是否存在CPU使用不均衡或者熱點。

mpstat預設只顯示CPU的整體使用情況,如下圖所示:

~# mpstat 1 Linux 5.4.0-99-generic (ambariserver-wangshuaihua-02.dev.kwaidc.com)    02/26/22    _x86_64_    (8 CPU) 15:14:04     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle 15:14:05     all    0.00    0.00    0.12    0.00    0.00    0.00    0.00    0.00    0.00   99.88 15:14:06     all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 15:14:07     all    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00

4. sar

sar工具可以用來觀測多項系統指標,針對CPU的引數有:

  • -P ALL:效果與mpstat -P ALL一樣,只是輸出的列稍微少一些
  • -u:與mpstat預設輸出結果一樣,系統平均指標
  • -q:輸出run-queue大小,RUNNABLE RUNNING與vmstat的r列內容一致
           初次使用sar工具可能會報錯,如果沒有sar工具則需要安裝,安裝後可能還會遇到以下錯誤

~# sar -P ALL Cannot open /var/log/sysstat/sa26: No such file or directory Please check if data collecting is enabled

解決方法:

~# sar  -o 2 3

~# sar -P ALL 1 -u -q Linux 5.4.0-99-generic (ambariserver-wangshuaihua-02.dev.kwaidc.com)    02/26/22    _x86_64_    (8 CPU) 15:27:19        CPU     %user     %nice   %system   %iowait    %steal     %idle 15:27:20        all      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          0      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          1      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          2      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          3      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          4      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          5      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          6      0.00      0.00      0.00      0.00      0.00    100.00 15:27:20          7      0.00      0.00      0.00      0.00      0.00    100.00

5. ps

ps方法是非常常用的工具,可以列出所有程序的相關資訊,命令格式有兩種:

  • BSD格式,引數不帶'-'字元
  • SVR4測試,引數帶'-'字元

BSD格式命令輸出如下所示:

~# ps aux USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND root           1  0.0  0.1 171060 13240 ?        Ss   Feb15   0:27 /sbin/init root           2  0.0  0.0      0     0 ?        S    Feb15   0:00 [kthreadd] root           3  0.0  0.0      0     0 ?        I<   Feb15   0:00 [rcu_gp] root           4  0.0  0.0      0     0 ?        I<   Feb15   0:00 [rcu_par_gp] root           6  0.0  0.0      0     0 ?        I<   Feb15   0:00 [kworker/0:0H-kblockd] root           9  0.0  0.0      0     0 ?        I<   Feb15   0:00 [mm_percpu_wq] root          10  0.0  0.0      0     0 ?        S    Feb15   0:00 [ksoftirqd/0] root          11  0.0  0.0      0     0 ?        I    Feb15   8:49 [rcu_sched]

SVR4格式命令輸出如下所示:

~# ps -ef UID          PID    PPID  C STIME TTY          TIME CMD root           1       0  0 Feb15 ?        00:00:27 /sbin/init root           2       0  0 Feb15 ?        00:00:00 [kthreadd] root           3       2  0 Feb15 ?        00:00:00 [rcu_gp] root           4       2  0 Feb15 ?        00:00:00 [rcu_par_gp] root           6       2  0 Feb15 ?        00:00:00 [kworker/0:0H-kblockd] root           9       2  0 Feb15 ?        00:00:00 [mm_percpu_wq] root          10       2  0 Feb15 ?        00:00:00 [ksoftirqd/0] root          11       2  0 Feb15 ?        00:08:49 [rcu_sched] root          12       2  0 Feb15 ?        00:00:06 [migration/0]

從命令的輸出結果上面,看起來BSD格式的輸出資訊更全一些,但是ps命令可以通過-o引數定製輸出列。針對CPU的使用情況,我們按照BSD格式的輸出來說,需要關注的是%CPU和TIME列:

  • %CPU:程序從啟動以來的平均CPU使用率
  • TIME:程序啟動以來總消耗的CPU時間使用者態 核心態(usr sys)

6. top

top命令可以以指定的時間間隔實時展示程序的CPU使用情況。

~# top top - 23:46:46 up 1135 days, 12:13,  1 user,  load average: 46.75, 60.82, 66.77 Tasks: 1660 total,   2 running, 1657 sleeping,   0 stopped,   1 zombie %Cpu(s): 28.5 us,  2.3 sy,  0.0 ni, 63.9 id,  4.7 wa,  0.0 hi,  0.5 si,  0.0 st KiB Mem : 19780201 total,   606332 free, 70851200 used, 12634449 buff/cache KiB Swap:        0 total,        0 free,        0 used. 12021227 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME  COMMAND 46652 yarn      20   0 8807788 3.459g  40876 S 428.9  1.8   7:49.67 java 69808 yarn      20   0 8643232 2.257g  41064 S 412.5  1.2   2:12.97 java 6608 yarn      20   0 9153288 3.615g  54376 S 404.9  1.9  17:39.61 java 8852 yarn      20   0 4104884 1.796g  47476 S 104.9  1.0   4:58.38 java 7359 hdfs      20   0 8616144 5.152g   3900 S  90.1  2.7 424070:32 java 46763 yarn      20   0 10.562g 7.527g 108768 S  66.1  4.0   1:09.90 java 28082 yarn      20   0 5371224 1.766g  34608 S  59.9  0.9   3:20.35 java 8030 yarn      20   0 4093672 1.656g  61588 S  52.0  0.9   5:33.91 java  51830 yarn      20   0 14.877g 0.010t  15560 S  33.2  5.3  64477:55 java

top命令的輸出結果中包含了系統整體CPU使用情況(第3行),和每個程序的CPU使用情況。對於每個程序CPU使用情況我們需要關注的是%CPU和TIME列:

  • %CPU:兩次螢幕重新整理期間程序的CPU使用率
  • TIME:程序啟動以來的總CPU使用時間,單位為秒,比如上面輸出的7359號程序已經消耗的CPU時間是424070分32秒

雖然top是一個非常基礎的分析工具,但是它對效能的損耗不可小覷,在負載重的機器上表現尤為明顯,需要謹慎使用。top對系統效能有較大的影響主要是因為要讀取/proc下面所有程序的資訊。因為top是對/proc做快照,所以很容易漏掉執行時間比較短的程序。

7. pidstat

pidstat可以用來分析單個程序或執行緒的CPU使用情況,預設情況下會滾動輸出。

# pidstat 1 Linux 3.10.0-693.5.2.el7.x86_64 (bjlt-h10366.sy)    02/27/2022  _x86_64_    (56 CPU) 12:00:34 AM   UID       PID    %usr %system  %guest    %CPU   CPU  Command 12:00:35 AM  1107     24628  100.00    4.59    0.00  100.00    51  java 12:00:35 AM  1107     29868  100.00    3.67    0.00  100.00    38  java 12:00:35 AM  1107     37421  100.00    2.75    0.00  100.00    45  java 12:00:35 AM  1107     38523    0.92    0.00    0.00    0.92    38  java 12:00:35 AM  1107     44470  100.00   26.61    0.00  100.00    40  java 12:00:35 AM  1107     48401  100.00   17.43    0.00  100.00    40  java 12:00:35 AM  1107     51584   27.52    2.75    0.00   30.28    29  java 12:00:35 AM  1107     51830    0.00  100.00    0.00  100.00    45  java

CPU分析常用引數:

  • -p ALL:顯示所有程序或執行緒CPU使用情況
  • -t:顯示執行緒粒度統計

8. time

time有兩個版本,一個是shell內建的,另外一個是/usr/bin/下的,這兩個有不同的使用效果
   shell內建time命令
   兩次對同一個檔案求MD5值

# time md5sum ambari-agent-2.6.2.0-0.x86_64.rpm 06e883c97b88079b0cc71a763fa2a99e  ambari-agent-2.6.2.0-0.x86_64.rpm real    0m0.417s user    0m0.175s sys 0m0.056s # time md5sum ambari-agent-2.6.2.0-0.x86_64.rpm 06e883c97b88079b0cc71a763fa2a99e  ambari-agent-2.6.2.0-0.x86_64.rpm real    0m0.242s user    0m0.177s sys 0m0.027s

從結果上可以看出第一次使用了0.417秒,使用者態使用了0.175秒,核心態使用了0.056秒,其中有0.186(0.417-0.175-0.056)秒的差距,猜測可能是花等磁碟io上了,第二次計算後時間差值縮小到了0.038秒,估計是這個檔案已經通過檔案系統快取到了記憶體中。

/usr/bin/time使用

# /usr/bin/time -v md5sum ambari-agent-2.6.2.0-0.x86_64.rpm 06e883c97b88079b0cc71a763fa2a99e  ambari-agent-2.6.2.0-0.x86_64.rpm Command being timed: "md5sum ambari-agent-2.6.2.0-0.x86_64.rpm" User time (seconds): 0.16 System time (seconds): 0.03 Percent of CPU this job got: 98% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.20 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 724 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 0 Minor (reclaiming a frame) page faults: 227 Voluntary context switches: 0 Involuntary context switches: 22 Swaps: 0 File system inputs: 0 File system outputs: 0 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096     Exit status: 0