​Linux CPU 效能優化指南

格伯納發表於2020-08-13

本文主要幫助理解 CPU 相關的效能指標,常見的 CPU 效能問題以及解決方案梳理。


系統平均負載

簡介

系統平均負載:是處於可執行或不可中斷狀態的平均程式數。

可執行程式:使用 CPU 或等待使用 CPU 的程式

不可中斷狀態程式:正在等待某些 IO 訪問,一般是和硬體互動,不可被打斷(不可被打斷的原因是為了保護系統資料一致,防止資料讀取錯誤)

檢視系統平均負載

首先top命令檢視程式執行狀態,如下:

 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND10760 user   20   0 3061604  84832   5956 S  82.4  0.6 126:47.61 Process29424 user   20   0   54060   2668   1360 R  17.6  0.0   0:00.03 **top**

程式狀態Status程式可執行狀態R不可中斷執行D(後續講解 top 時會詳細說明)

top檢視系統平均負載:

top - 13:09:42 up 888 days, 21:32,  8 users,  load average: 19.95, 14.71, 14.01Tasks: 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/cacheKiB Swap:        0 total,        0 free,        0 used.  6654506 avail Mem

這裡的load average就表示系統最近 1 分鐘、5 分鐘、15 分鐘的系統瓶頸負載。

uptime檢視系統瓶頸負載

[root /home/user]# uptime 13:11:01 up 888 days, 21:33,  8 users,  load average: 17.20, 14.85, 14.10
檢視 CPU 核資訊

系統平均負載和 CPU 核數密切相關,我們可以通過以下命令檢視當前機器 CPU 資訊:

lscpu檢視 CPU 資訊:

[root@Tencent-SNG /home/user_00]# lscpuArchitecture:          x86_64CPU op-mode(s):        32-bit, 64-bitByte Order:            Little EndianCPU(s):                8...L1d cache:             32KL1i cache:             32KL2 cache:              4096KNUMA node0 CPU(s):     0-7  // NUMA架構資訊

cat /proc/cpuinfo檢視每個 CPU 核的資訊:

processor       : 7   // 核編號7vendor_id       : GenuineIntelcpu family      : 6model           : 6...
系統平均負載升高的原因

一般來說,系統平均負載升高意味著 CPU 使用率上升。但是他們沒有必然聯絡,CPU 密集型計算任務較多一般系統平均負載會上升,但是如果 IO 密集型任務較多也會導致系統平均負載升高但是此時的 CPU 使用率不一定高,可能很低因為很多程式都處於不可中斷狀態,等待 CPU 排程也會升高系統平均負載。

所以假如我們系統平均負載很高,但是 CPU 使用率不是很高,則需要考慮是否系統遇到了 IO 瓶頸,應該優化 IO 讀寫速度。

所以系統是否遇到 CPU 瓶頸需要結合 CPU 使用率,系統瓶頸負載一起檢視(當然還有其他指標需要對比檢視,下面繼續講解)

案例問題排查

stress是一個施加系統壓力和壓力測試系統的工具,我們可以使用stress工具壓測試 CPU,以便方便我們定位和排查 CPU 問題。

yum install stress // 安裝stress工具
stress 命令使用
 // --cpu 8:8個程式不停的執行sqrt()計算操作 // --io 4:4個程式不同的執行sync()io操作(刷盤) // --vm 2:2個程式不停的執行malloc()記憶體申請操作 // --vm-bytes 128M:限制1個執行malloc的程式申請記憶體大小 stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10s

我們這裡主要驗證 CPU、IO、程式數過多的問題

CPU 問題排查

使用stress -c 1模擬 CPU 高負載情況,然後使用如下命令觀察負載變化情況:

uptime:使用uptime檢視此時系統負載:

# -d 參數列示高亮顯示變化的區域$ watch -d uptime... load average: 1.00, 0.75, 0.39

mpstat:使用mpstat -P ALL 1則可以檢視每一秒的 CPU 每一核變化資訊,整體和top類似,好處是可以把每一秒(自定義)的資料輸出方便觀察資料的變化,最終輸出平均資料:

13:14:53     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle13:14:58     all   12.89    0.00    0.18    0.00    0.00    0.03    0.00    0.00    0.00   86.9113:14:58       0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.0013:14:58       1    0.40    0.00    0.20    0.00    0.00    0.20    0.00    0.00    0.00   99.20

由以上輸出可以得出結論,當前系統負載升高,並且其中 1 個核跑滿主要在執行使用者態任務,此時大多數屬於業務工作。所以此時需要查哪個程式導致單核 CPU 跑滿:

pidstat:使用pidstat -u 1則是每隔 1 秒輸出當前系統程式、CPU 資料:

13:18:00      UID       PID    %usr %system  %guest    %CPU   CPU  Command13:18:01        0         1    1.00    0.00    0.00    1.00     4  systemd13:18:01        0   3150617  100.00    0.00    0.00  100.00     0  stress...

top:當然最方便的還是使用top命令檢視負載情況

top - 13:19:06 up 125 days, 20:01,  3 users,  load average: 0.99, 0.63, 0.42Tasks: 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 stKiB Mem : 16166056 total,  3118532 free,  9550108 used,  3497416 buff/cacheKiB Swap:        0 total,        0 free,        0 used.  6447640 avail Mem
   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND3150617 root      20   0   10384    120      0 R 100.0  0.0   4:36.89 stress

此時可以看到是stress佔用了很高的 CPU。

IO 問題排查

我們使用stress -i 1來模擬 IO 瓶頸問題,即死迴圈執行 sync 刷盤操作:uptime:使用uptime檢視此時系統負載:


$ watch -d uptime...,  load average: 1.06, 0.58, 0.37

mpstat:檢視此時 IO 消耗,但是實際上我們發現這裡 CPU 基本都消耗在了 sys 即系統消耗上。

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idleAverage:     all    0.33    0.00   12.64    0.13    0.00    0.00    0.00    0.00    0.00   86.90Average:       0    0.00    0.00   99.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00Average:       1    0.00    0.00    0.33    0.00    0.00    0.00    0.00    0.00    0.00   99.67

IO 無法升高的問題

iowait 無法升高的問題,是因為案例中 stress 使用的是 sync()系統呼叫,它的作用是重新整理緩衝區記憶體到磁碟中。對於新安裝的虛擬機器,緩衝區可能比較小,無法產生大的 IO 壓力,這樣大部分就都是系統呼叫的消耗了。所以,你會看到只有系統 CPU 使用率升高。解決方法是使用 stress 的下一代 stress-ng,它支援更豐富的選項,比如stress-ng -i 1 --hdd 1 --timeout 600(--hdd 表示讀寫臨時檔案)。

Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idleAverage:     all    0.25    0.00    0.44   26.22    0.00    0.00    0.00    0.00    0.00   73.09Average:       0    0.00    0.00    1.02   98.98    0.00    0.00    0.00    0.00    0.00    0.00

pidstat:同上(略)

可以看出 CPU 的 IO 升高導致系統平均負載升高。我們使用pidstat查詢具體是哪個程式導致 IO 升高的。

top:這裡使用 top 依舊是最方面的檢視綜合引數,可以得出stress是導致 IO 升高的元凶。

pidstat 沒有 iowait 選項:可能是 CentOS 預設的sysstat太老導致,需要升級到 11.5.5 之後的版本才可用。

程式數過多問題排查

程式數過多這個問題比較特殊,如果系統執行了很多程式超出了 CPU 執行能,就會出現等待 CPU 的程式。使用stress -c 24來模擬執行 24 個程式(我的 CPU 是 8 核)uptime:使用uptime檢視此時系統負載:

$ watch -d uptime...,  load average: 18.50, 7.13, 2.84

mpstat:同上(略)

pidstat:同上(略)

可以觀察到此時的系統處理嚴重過載的狀態,平均負載高達 18.50

top:我們還可以使用top命令檢視此時Running狀態的程式數,這個數量很多就表示系統正在執行、等待執行的程式過多。

總結

通過以上問題現象及解決思路可以總結出:

  1. 平均負載高有可能是 CPU 密集型程式導致的
  2. 平均負載高並不一定代表 CPU 使用率高,還有可能是 I/O 更繁忙了
  3. 當發現負載高的時候,你可以使用 mpstat、pidstat 等工具,輔助分析負載的來源

總結工具:mpstatpidstattopuptime

CPU 上下文切換

CPU 上下文:CPU 執行每個任務都需要知道任務從哪裡載入、又從哪裡開始執行,也就是說,需要系統事先幫它設定好 CPU 暫存器和程式計數器(Program Counter,PC)包括 CPU 暫存器在內都被稱為 CPU 上下文。

CPU 上下文切換:CPU 上下文切換,就是先把前一個任務的 CPU 上下文(也就是 CPU 暫存器和程式計數器)儲存起來,然後載入新任務的上下文到這些暫存器和程式計數器,最後再跳轉到程式計數器所指的新位置,執行新任務。

CPU 上下文切換:分為程式上下文切換執行緒上下文切換以及中斷上下文切換

程式上下文切換

從使用者態切換到核心態需要通過系統呼叫來完成,這裡就會發生程式上下文切換(特權模式切換),當切換回使用者態同樣發生上下文切換。

一般每次上下文切換都需要幾十納秒到數微秒的 CPU 時間,如果切換較多還是很容易導致 CPU 時間的浪費在暫存器、核心棧以及虛擬記憶體等資源的儲存和恢復上,這裡同樣會導致系統平均負載升高

Linux 為每個 CPU 維護一個就緒佇列,將 R 狀態程式按照優先順序和等待 CPU 時間排序,選擇最需要的 CPU 程式執行。這裡執行程式就涉及了程式上下文切換的時機:

  1. 程式時間片耗盡、。
  2. 程式在系統資源不足(記憶體不足)。
  3. 程式主動sleep
  4. 有優先順序更高的程式執行。
  5. 硬中斷髮生。

執行緒上下文切換

執行緒和程式:

  1. 當程式只有一個執行緒時,可以認為程式就等於執行緒。
  2. 當程式擁有多個執行緒時,這些執行緒會共享相同的虛擬記憶體和全域性變數等資源。這些資源在上下文切換時是不需要修改的。
  3. 執行緒也有自己的私有資料,比如棧和暫存器等,這些在上下文切換時也是需要儲存的。

所以執行緒上下文切換包括了 2 種情況:

  1. 不同程式的執行緒,這種情況等同於程式切換。
  2. 通程式的執行緒切換,只需要切換執行緒私有資料、暫存器等不共享資料。

中斷上下文切換

中斷處理會打斷程式的正常排程和執行,轉而呼叫中斷處理程式,響應裝置事件。而在打斷其他程式時,就需要將程式當前的狀態儲存下來,這樣在中斷結束後,程式仍然可以從原來的狀態恢復執行。

對同一個 CPU 來說,中斷處理比程式擁有更高的優先順序,所以中斷上下文切換並不會與程式上下文切換同時發生。由於中斷會打斷正常程式的排程和執行,所以大部分中斷處理程式都短小精悍,以便儘可能快的執行結束。

檢視系統上下文切換

vmstat:工具可以檢視系統的記憶體、CPU 上下文切換以及中斷次數:

// 每隔1秒輸出$ vmstat 1procs -----------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  017  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:則為每秒的上下文切換次數。

in:則為每秒的中斷次數。

r:就緒佇列長度,正在執行或等待 CPU 的程式。

b:不可中斷睡眠狀態的程式數,例如正在和硬體互動。

pidstat:使用pidstat -w選項檢視具體程式的上下文切換次數:

$ pidstat -w -p 3217281 110:19:13      UID       PID   cswch/s nvcswch/s  Command10:19:14        0   3217281      0.00     18.00  stress10:19:15        0   3217281      0.00     18.00  stress10:19:16        0   3217281      0.00     28.71  stress

其中cswch/snvcswch/s表示自願上下文切換和非自願上下文切換。

自願上下文切換:是指程式無法獲取所需資源,導致的上下文切換。比如說, I/O、記憶體等系統資源不足時,就會發生自願上下文切換。

非自願上下文切換:則是指程式由於時間片已到等原因,被系統強制排程,進而發生的上下文切換。比如說,大量程式都在爭搶 CPU 時,就容易發生非自願上下文切換

案例問題排查

這裡我們使用sysbench工具模擬上下文切換問題。

先使用vmstat 1檢視當前上下文切換資訊:

$ vmstat 1procs -----------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 個執行緒執行任務,此時我們再次vmstat 1檢視上下文切換資訊:

$ vmstat 1procs -----------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  014  0      0 323488 3385980 5474828    0    0    64   788 111647 3745536 24 61 15  0  014  0      0 323576 3386028 5474856    0    0     8     0 118383 4317546 25 64 11  0  016  0      0 315560 3386100 5475056    0    0     8    16 115253 4553099 22 68  9  0  0

我們可以明顯的觀察到:

  1. 當前 cs、in 此時劇增。
  2. sy+us 的 CPU 佔用超過 90%。
  3. r 就緒佇列長度達到 16 個超過了 CPU 核心數 8 個。
分析 cs 上下文切換問題

我們使用pidstat檢視當前 CPU 資訊和具體的程式上下文切換資訊:

// -w表示檢視程式切換資訊,-u檢視CPU資訊,-t檢視執行緒切換資訊$ pidstat -w -u -t 1
10:35:01      UID       PID    %usr %system  %guest    %CPU   CPU  Command10:35:02        0   3383478   67.33  100.00    0.00  100.00     1  sysbench
10:35:01      UID       PID   cswch/s nvcswch/s  Command10:45:39        0   3509357         -      1.00      0.00  kworker/2:210:45:39        0         -   3509357      1.00      0.00  |__kworker/2:210:45:39        0         -   3509702  38478.00  45587.00  |__sysbench10:45:39        0         -   3509703  39913.00  41565.00  |__sysbench

所以我們可以看到大量的sysbench執行緒存在很多的上下文切換。

分析 in 中斷問題

我們可以檢視系統的watch -d cat /proc/softirqs以及watch -d cat /proc/interrupts來檢視系統的軟中斷和硬中斷(核心中斷)。我們這裡主要觀察/proc/interrupts即可。

$ watch -d cat /proc/interruptsRES:  900997016  912023527  904378994  902594579  899800739  897500263  895024925  895452133   Rescheduling interrupts

這裡明顯看出重排程中斷(RES)增多,這個中斷表示喚醒空閒狀態 CPU 來排程新任務執行,

總結

  1. 自願上下文切換變多了,說明程式都在等待資源,有可能發生了 I/O 等其他問題。
  2. 非自願上下文切換變多了,說明程式都在被強制排程,也就是都在爭搶 CPU,說明 CPU 的確成了瓶頸。
  3. 中斷次數變多了,說明 CPU 被中斷處理程式佔用,還需要通過檢視/proc/interrupts檔案來分析具體的中斷型別。

CPU 使用率

除了系統負載、上下文切換資訊,最直觀的 CPU 問題指標就是 CPU 使用率資訊。Linux 通過/proc虛擬檔案系統向使用者控制元件提供系統內部狀態資訊,其中/proc/stat則是 CPU 和任務資訊統計。

$ cat /proc/stat | grep cpucpu  6392076667 1160 3371352191 52468445328 3266914 37086 36028236 20721765 0 0cpu0 889532957 175 493755012 6424323330 2180394 37079 17095455 3852990 0 0...

這裡每一列的含義如下:

  1. user(通常縮寫為 us),代表使用者態 CPU 時間。注意,它不包括下面的 nice 時間,但包括了 guest 時間。
  2. nice(通常縮寫為 ni),代表低優先順序使用者態 CPU 時間,也就是程式的 nice 值被調整為 1-19 之間時的 CPU 時間。這裡注意,nice 可取值範圍是 -20 到 19,數值越大,優先順序反而越低。
  3. system(通常縮寫為 sys),代表核心態 CPU 時間。
  4. idle(通常縮寫為 id),代表空閒時間。注意,它不包括等待 I/O 的時間(iowait)。
  5. iowait(通常縮寫為 wa),代表等待 I/O 的 CPU 時間。
  6. irq(通常縮寫為 hi),代表處理硬中斷的 CPU 時間。
  7. softirq(通常縮寫為 si),代表處理軟中斷的 CPU 時間。
  8. steal(通常縮寫為 st),代表當系統執行在虛擬機器中的時候,被其他虛擬機器佔用的 CPU 時間。
  9. guest(通常縮寫為 guest),代表通過虛擬化執行其他作業系統的時間,也就是執行虛擬機器的 CPU 時間。
  10. guest_nice(通常縮寫為 gnice),代表以低優先順序執行虛擬機器的時間。

這裡我們可以使用toppspidstat等工具方便的查詢這些資料,可以很方便的看到 CPU 使用率很高的程式,這裡我們可以通過這些工具初步定為,但是具體的問題原因還需要其他方法繼續查詢。

這裡我們可以使用perf top方便檢視熱點資料,也可以使用perf record可以將當前資料儲存起來方便後續使用perf report檢視。

CPU 使用率問題排查

這裡總結一下 CPU 使用率問題及排查思路:

  1. 使用者 CPU 和 Nice CPU 高,說明使用者態程式佔用了較多的 CPU,所以應該著重排查程式的效能問題。
  2. 系統 CPU 高,說明核心態佔用了較多的 CPU,所以應該著重排查核心執行緒或者系統呼叫的效能問題。
  3. I/O 等待 CPU 高,說明等待 I/O 的時間比較長,所以應該著重排查系統儲存是不是出現了 I/O 問題。
  4. 軟中斷和硬中斷高,說明軟中斷或硬中斷的處理程式佔用了較多的 CPU,所以應該著重排查核心中的中斷服務程式。

CPU 問題排查套路

CPU 使用率

CPU 使用率主要包含以下幾個方面:

  1. 使用者 CPU 使用率,包括使用者態 CPU 使用率(user)和低優先順序使用者態 CPU 使用率(nice),表示 CPU 在使用者態執行的時間百分比。使用者 CPU 使用率高,通常說明有應用程式比較繁忙。
  2. 系統 CPU 使用率,表示 CPU 在核心態執行的時間百分比(不包括中斷)。系統 CPU 使用率高,說明核心比較繁忙。
  3. 等待 I/O 的 CPU 使用率,通常也稱為 iowait,表示等待 I/O 的時間百分比。iowait 高,通常說明系統與硬體裝置的 I/O 互動時間比較長。
  4. 軟中斷和硬中斷的 CPU 使用率,分別表示核心呼叫軟中斷處理程式、硬中斷處理程式的時間百分比。它們的使用率高,通常說明系統發生了大量的中斷。
  5. 除在虛擬化環境中會用到的竊取 CPU 使用率(steal)和客戶 CPU 使用率(guest),分別表示被其他虛擬機器佔用的 CPU 時間百分比,和執行客戶虛擬機器的 CPU 時間百分比。

平均負載

反應了系統的整體負載情況,可以檢視過去 1 分鐘、過去 5 分鐘和過去 15 分鐘的平均負載。

上下文切換

上下文切換主要關注 2 項指標:

  1. 無法獲取資源而導致的自願上下文切換。
  2. 被系統強制排程導致的非自願上下文切換。

CPU 快取命中率

CPU 的訪問速度遠大於記憶體訪問,這樣在 CPU 訪問記憶體時不可避免的要等待記憶體響應。為了協調 2 者的速度差距出現了 CPU 快取(多級快取)。如果 CPU 快取命中率越高則效能會更好,我們可以使用以下工具檢視 CPU 快取命中率,工具地址、專案地址 perf-tools

# ./cachestat -tCounting cache functions... Output every 1 seconds.TIME         HITS   MISSES  DIRTIES    RATIO   BUFFERS_MB   CACHE_MB08:28:57      415        0        0   100.0%            1        19108:28:58      411        0        0   100.0%            1        19108:28:59      362       97        0    78.9%            0          808:29:00      411        0        0   100.0%            0          908:29:01      775    20489        0     3.6%            0         8908:29:02      411        0        0   100.0%            0         8908:29:03     6069        0        0   100.0%            0         8908:29:04    15249        0        0   100.0%            0         8908:29:05      411        0        0   100.0%            0         8908:29:06      411        0        0   100.0%            0         8908:29:07      411        0        3   100.0%            0         89[...]

總結

通過效能指標查工具(CPU 相關)

效能指標工具說明
平均負載uptime
top
uptime 簡單展示最近一段時間的平均負載
top 展示更多指標
CPU 使用率vmstat
mpstat
top
sar
/proc/stat
top、vmstat、mpstat 只可以動態檢視當前,而 sar 可以檢視歷史
/proc/stat 是其他效能工具的資料來源
程式 CPU 使用率top
pidstat
ps
htop
atop
top、ps 可以以排序方式展示程式 CPU、pidstat 不可排序展示
htop、atop 則以不同顏色展示各類資料更直觀
系統上下文切換vmstat展示上下文切換此時、執行狀態、不可中斷狀態程式數量
程式上下文切換pidstat展示項很多,包括程式上下文切換資訊
軟中斷top
/proc/softirqs
mpstat
top 可檢視軟中斷 CPU 使用率
/proc/softirqs 和 mpstat 則可以檢視每個 CPU 上的累計資訊
硬中斷vmstat
/proc/interrupts
vmstat 檢視總中斷次數資訊
/proc/interrupts 檢視各種中斷在每個 CPU 核心上的累計資訊
網路dstat
sar
tcpdump
dstat、sar 較詳細的展示出總的網路收發情況
tcpdump 提供動態抓取資料包的能力
IOdstat、sar2 者都提供了詳細的 IO 整體情況
CPU 資訊/proc/cpuinfo
lscpu
都可以檢視 CPU 資訊
系統分析perf
execsnoop
perf 分析各種核心函式呼叫、熱點函式資訊
execsnoop 監控短時程式

根據工具查效能指標(CPU 相關)

效能工具CPU 效能指標
uptime5、10、15 分鐘內的平均負載展示
top平均負載、執行佇列、CPU 各項使用率、程式狀態和 CPU 使用率
htoptop 增強版,以不同顏色區分不同型別程式,展示更直觀
atopCPU、記憶體、磁碟、網路資源全訪問監控,十分齊全
vmstat系統整體 CPU 使用率、上下文切換次數、中斷次數,還包括處於執行(r)和不可中斷狀態(b)的程式數量
pidstat程式、執行緒(-t)的每個 CPU 佔用資訊,中斷上下文切換次數
/proc/softirqs展示每個 CPU 上的軟中斷型別及次數
/proc/inerrupts展示每個 CPU 上的硬中斷型別及次數
ps每個程式的狀態和 CPU 使用率
pstree程式的父子關係展示
dstat系統整體 CPU 使用率(以及相關 IO、網路資訊)
sar系統整體 CPU 使用率,以及使用率歷史資訊
strace跟蹤程式的系統呼叫
perfCPU 效能事件分析,例如:函式呼叫鏈、CPU 快取命中率、CPU 排程等
execsnoop短時程式分析

CPU 問題排查方向

有了以上效能工具,在實際遇到問題時我們並不可能全部效能工具跑一遍,這樣效率也太低了,所以這裡可以先執行幾個常用的工具 top、vmstat、pidstat 分析系統大概的執行情況然後在具體定位原因。

top 系統CPU => vmstat 上下文切換次數 => pidstat 非自願上下文切換次數 => 各類程式分析工具(perf strace ps execsnoop pstack)
top 使用者CPU => pidstat 使用者CPU => 一般是CPU計算型任務
top 殭屍程式 =>  各類程式分析工具(perf strace ps execsnoop pstack)
top 平均負載 => vmstat 執行狀態程式數 =>  pidstat 使用者CPU => 各類程式分析工具(perf strace ps execsnoop pstack)
top 等待IO CPU => vmstat 不可中斷狀態程式數  => IO分析工具(dstat、sar -d)
top 硬中斷 => vmstat 中斷次數 => 檢視具體中斷型別(/proc/interrupts)
top 軟中斷 => 檢視具體中斷型別(/proc/softirqs) => 網路分析工具(sar -n、tcpdump) 或者 SCHED(pidstat 非自願上下文切換)

CPU 問題優化方向

效能優化往往是多方面的,CPU、記憶體、網路等都是有關聯的,這裡暫且給出 CPU 優化的思路,以供參考。

程式優化
  1. 基本優化:程式邏輯的優化比如減少迴圈次數、減少記憶體分配,減少遞迴等等。
  2. 編譯器優化:開啟編譯器優化選項例如gcc -O2對程式程式碼優化。
  3. 演算法優化:降低蘇研發複雜度,例如使用nlogn的排序演算法,使用logn的查詢演算法等。
  4. 非同步處理:例如把輪詢改為通知方式
  5. 多執行緒代替多程式:某些場景下多執行緒可以代替多程式,因為上下文切換成本較低
  6. 快取:包括多級快取的使用(略)加快資料訪問
系統優化
  1. CPU 繫結:繫結到一個或多個 CPU 上,可以提高 CPU 快取命中率,減少跨 CPU 排程帶來的上下文切換問題
  2. CPU 獨佔:跟 CPU 繫結類似,進一步將 CPU 分組,並通過 CPU 親和性機制為其分配程式。
  3. 優先順序調整:使用 nice 調整程式的優先順序,適當降低非核心應用的優先順序,增高核心應用的優先順序,可以確保核心應用得到優先處理。
  4. 為程式設定資源限制:使用 Linux cgroups 來設定程式的 CPU 使用上限,可以防止由於某個應用自身的問題,而耗盡系統資源。
  5. NUMA 優化:支援 NUMA 的處理器會被劃分為多個 Node,每個 Node 有本地的記憶體空間,這樣 CPU 可以直接訪問本地空間記憶體。
  6. 中斷負載均衡:無論是軟中斷還是硬中斷,它們的中斷處理程式都可能會耗費大量的 CPU。開啟 irqbalance 服務或者配置 smp_affinity,就可以把中斷處理過程自動負載均衡到多個 CPU 上。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31509949/viewspace-2711585/,如需轉載,請註明出處,否則將追究法律責任。

相關文章