Linux CPU 上下文切換的故障排查

roc_guo發表於2022-10-09
檢查 CPU 的上下文切換

我們知道,過多的上下文切換會消耗 CPU 的時間來儲存和恢復暫存器、程式計數器、核心棧和虛擬記憶體等資料,從而導致系統效能顯著下降。

既然上下文切換對系統效能的影響如此之大,那麼我們如何檢查它呢?好了,你可以使用 vmstat 工具來查詢你係統的上下文切換。

vmstat

vmstat 是一種常用的系統效能分析工具。主要用於分析記憶體使用情況,也常用於分析 CPU 上下文切換和中斷的次數。

例如 vmstat 5(5 秒輸出間隔):
Linux CPU 上下文切換的故障排查Linux CPU 上下文切換的故障排查

讓我們看一下輸出:

  • cs(context switch):每秒上下文切換的次數。
  • in(interrupt):每秒的中斷數。
  • r(running | runnable):就緒佇列的長度,即正在執行和等待 CPU 的程式數。
  • b(blocked):處於不間斷睡眠狀態的程式數。

在上面的例子中,我們可以看到上下文切換次數為 33 次,系統中斷次數為 25 次,就緒佇列長度,不間斷狀態程式數均為 0。

pidstat

vmstat 工具只給出了系統的整體上下文切換的資訊。要檢視每個程式的詳細資訊,您需要使用 pidstat。新增 -w 選項,您可以看到每個程式的上下文切換:

例如:

$ pidstat -w 5
Linux 4.15.0 (ubuntu)  09/23/18  _x86_64_  (2 CPU)
08:18:26      UID       PID   cswch/s nvcswch/s  Command
08:18:31        0         1      0.20      0.00  systemd
08:18:31        0         8      5.40      0.00  rcu_sched
...

結果中有兩列需要我們注意:cswch 和 nvcswch。其中,cswch 表示每秒自願上下文切換的次數,nvcswch 表示每秒非自願上下文切換的次數。

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

非自願上下文切換:指程式因時間片已過期而被系統強制重新排程時發生的上下文切換。例如,當大量程式競爭 CPU 時,很容易發生非自願的上下文切換。

您必須牢記這兩個概念,因為它們意味著不同的效能問題。

案例分析

既然您知道如何檢視這些指標,那麼就會出現另一個問題,上下文切換頻率多久才是正常的呢?讓我們看一個示例案例。

我們將使用 sysbench ,一個多執行緒的基準測試工具透過生成負載來模擬上下文切換過多的問題。假設您已經在 Linux 系統上安裝了 sysbench 和 sysstat。

在我們模擬負載之前,讓我們在一個終端中執行一下 vmstat:

Linux CPU 上下文切換的故障排查Linux CPU 上下文切換的故障排查

在這裡可以看到當前的上下文切換次數 cs 是 35,中斷次數 in 是 19,r 和 b 都是 0。由於我目前沒有其他任務在執行,因此它們是空閒系統中的上下文切換數量。

現在讓我們執行 sysbench 來模擬多執行緒排程系統的瓶頸:

$ sysbench --threads=10 --max-time=300 threads run

現在,您應該會看到 vmstat 輸出了與上面不同的結果:

應該可以發現 cs 欄的上下文切換次數從之前的 35 次突增到 139 萬次。同時,注意觀察其他幾個指標:

r:就緒佇列的長度已達到 8
us 和 sy:us 和 sy 的 CPU 使用率加起來是 100%,系統 CPU 使用率是 84%,說明 CPU 主要被核心佔用。
in:中斷數也上升到了 10000,說明中斷處理也是一個潛在的問題。

結合這些指標我們可以知道系統的就緒佇列太長了,也就是有太多的程式在執行等待 CPU,導致大量的上下文切換,而大量的上下文切換導致了系統 CPU 使用率的增長。

那麼是什麼過程導致了這些問題呢?

我們繼續分析,同時在第三個終端使用 pidstat,看看 CPU 和程式上下文切換的情況:

$ pidstat -w -u 1
08:06:33      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:06:34        0     10488   30.00  100.00    0.00    0.00  100.00     0  sysbench
08:06:34        0     26326    0.00    1.00    0.00    0.00    1.00     0  kworker/u4:2
08:06:33      UID       PID   cswch/s nvcswch/s  Command
08:06:34        0         8     11.00      0.00  rcu_sched
08:06:34        0        16      1.00      0.00  ksoftirqd/1
08:06:34        0       471      1.00      0.00  hv_balloon
08:06:34        0      1230      1.00      0.00  iscsid
08:06:34        0      4089      1.00      0.00  kworker/1:5
08:06:34        0      4333      1.00      0.00  kworker/0:3
08:06:34        0     10499      1.00    224.00  pidstat
08:06:34        0     26326    236.00      0.00  kworker/u4:2
08:06:34     1000     26784    223.00      0.00  sshd

從 pidstat 的輸出可以發現,CPU 使用率的增加確實是 sysbench 造成的,它的 CPU 使用率已經達到了 100%。但上下文切換來自其他程式,包括非自願上下文切換頻率最高的 pidstat,以及自願上下文切換頻率最高的核心執行緒 kworker 和 sshd。

注意:預設情況下 pidstat 只顯示程式的上下文切換,如果要檢視實際執行緒的上下文切換,請新增 -t 選項。

中斷

要找出中斷數量也很高的原因所在,您可以檢查 /proc/interrupts 檔案。該檔案會提供一個只讀的中斷使用情況。

$ watch -d cat /proc/interrupts
           CPU0       CPU1
...
RES:    2450431    5279697   Rescheduling interrupts
...

觀察一段時間後,可以發現變化最快的是重新排程中斷(RES, REScheduling interrupt)。這種中斷型別表明處於空閒狀態的 CPU 被喚醒以排程新的任務執行。所以這裡的中斷增加是因為太多的任務排程問題,這和前面上下文切換次數的分析結果是一致的

現在回到最初的問題,每秒多少次上下文切換是正常的?

這個值實際上取決於系統本身的 CPU 效能。在我看來,如果系統的上下文切換次數比較穩定的話,幾百到一萬應該是正常的。但是,當上下文切換次數超過 10000,或者切換次數快速增加時,很可能是出現了效能問題。

結論

此時,你應該可以根據上下文切換的型別做一些具體的分析了。

自願上下文切換較多,說明程式在等待資源,可能會出現 I/O 飽和等其他問題。
非自願上下文切換較多,說明程式正在被強制排程,也就是都在爭搶 CPU,說明 CPU 確實產生了瓶頸。
中斷次數增多,說明 CPU 被中斷處理程式佔用,需要透過檢視 /proc/interrupts 檔案來分析具體的中斷型別。


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

相關文章