04-基礎篇:經常說的 CPU 上下文切換是什麼意思?(下)
阿新 • • 發佈:2021-11-09
怎麼檢視系統的上下文切換情況
過多的上下文切換,會把CPU時間消耗在暫存器、核心棧以及虛擬記憶體等資料的儲存和恢復上 縮短程序真正執行的時間,成了系統性能大幅下降的一個元凶 vmstat是一個常用的系統性能分析工具,主要用來分析系統的記憶體使用情況,也常用來分析CPU上下文切換和中斷的次數 # 每隔5秒輸出1組資料 [root@local_sa_192-168-1-6 ~]# 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 0 0 0 2549872 2112 842612 0 0 0 0 41 73 0 0 100 0 0 # 輸出結果解析 # cs(context switch)是每秒上下文切換的次數 # in(interrupt)則是每秒中斷的次數 # r(Running or Runnable)是就緒佇列的長度,也就是正在執行和等待CPU的程序數 # b(Blocked)則是處於不可中斷睡眠狀態的程序數 可以看到,這個例子中的上下文切換次數cs是73次,而系統中斷次數in則是41次,而就緒佇列長度r和不可中斷狀態程序數b都是0 pidstat vmstat只給出了系統總體的上下文切換情況,要想檢視每個程序的詳細情況,就需要使用pidstat 加上-w選項,就可以檢視每個程序上下文切換的情況了 # 每隔5秒輸出1組資料 [root@local_sa_192-168-1-6 ~]# pidstat -w 5 Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 2021年11月09日 _x86_64_ (2 CPU) 16時02分50秒 UID PID cswch/s nvcswch/s Command 16時02分55秒 0 6 0.60 0.00 ksoftirqd/0 16時02分55秒 0 9 3.98 0.00 rcu_sched 16時02分55秒 0 11 0.20 0.00 watchdog/0 16時02分55秒 0 12 0.20 0.00 watchdog/1 16時02分55秒 0 35 0.20 0.00 khugepaged ...... 平均時間: UID PID cswch/s nvcswch/s Command 平均時間: 0 6 0.60 0.00 ksoftirqd/0 平均時間: 0 9 3.98 0.00 rcu_sched 平均時間: 0 11 0.20 0.00 watchdog/0 平均時間: 0 12 0.20 0.00 watchdog/1 平均時間: 0 35 0.20 0.00 khugepaged ...... # 輸出結果分析 這個結果中有兩列內容是重點關注物件。 一個是cswch,表示每秒自願上下文切換(voluntary context switches)的次數, 一個是nvcswch,表示每秒非自願上下文切換(non voluntary context switches)的次數 【自願上下文切換】是指程序無法獲取所需資源,導致的上下文切換 比如說,I/O、記憶體等系統資源不足時,就會發生自願上下文切換 【非自願上下文切換】則是指程序由於時間片已到等原因,被系統強制排程,進而發生的上下文切換 比如說,大量程序都在爭搶CPU時,就容易發生非自願上下文切換
案例
將使用sysbench來模擬系統多執行緒排程切換的情況
sysbench是一個多執行緒的基準測試工具,一般用來評估不同系統引數下的資料庫負載情況
當然,在這次案例中,我們只把它當成一個異常程序來看,作用是模擬上下文切換過多的問題
預先安裝sysbench和sysstat包
[root@local_sa_192-168-1-6 ~]# yum install sysbench sysstat -y
1.在第一個終端先用 vmstat 看一下空閒系統的上下文切換次數
# 間隔1秒輸出1組資料 [root@local_sa_192-168-1-6 ~]# vmstat 1 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 2462268 2112 929712 0 0 5 17 39 75 1 0 99 0 0 # 上下文切換次數cs是75 # 中斷次數in是39 # r和b都是0。因為這會兒沒有執行其他任務,所以它們就是空閒系統的上下文切換次數
2.然後再在第一個終端執行sysbench,模擬系統多執行緒排程的瓶頸
# 以10個執行緒執行5分鐘的基準測試,模擬多執行緒切換的問題
[root@local_sa_192-168-1-6 ~]# sysbench --threads=10 --max-time=300 threads run
......
Threads started!
3.在第二個終端執行 vmstat ,觀察上下文切換情況
# 每隔1秒輸出1組資料,如果要停止 ctrl+c [root@local_sa_192-168-1-6 ~]# 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 8 0 0 2459604 2112 929964 0 0 0 0 36236 732600 25 73 2 0 0 #可以發現 #cs列的上下文切換次數從之前的75驟然上升到了73萬 #r列就緒佇列的長度已經到了8,遠遠超過了系統CPU的個數2,所以肯定會有大量的CPU競爭 #us和sy列這兩列的CPU使用率加起來上升到了98%,其中系統CPU使用率,也就是sy列高達73%,說明CPU主要是被核心佔用了 #in列中斷次數也上升到了3萬左右,說明中斷處理也是個潛在的問題 綜合這幾個指標,我們可以知道,系統的就緒佇列過長,也就是正在執行和等待CPU的程序數過多 導致了大量的上下文切換,而上下文切換又導致了系統CPU的佔用率升高
4.在第三個終端再用pidstat來看一下,CPU和程序上下文切換的情況
那麼到底是什麼程序導致了這些問題呢?
pidstat
# 每隔1秒輸出1組資料
# -w引數表示輸出程序上下文切換指標
# -u引數表示輸出cpu使用指標
[root@local_sa_192-168-1-6 ~]# pidstat -w -u 1
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 2021年11月09日 _x86_64_ (2 CPU)
16時20分34秒 UID PID %usr %system %guest %wait %CPU CPU Command
16時20分35秒 0 31005 49.00 147.00 0.00 0.00 196.00 1 sysbench
16時20分35秒 0 31100 0.00 1.00 0.00 0.00 1.00 0 pidstat
16時20分34秒 UID PID cswch/s nvcswch/s Command
16時20分35秒 0 6 2.00 0.00 ksoftirqd/0
16時20分35秒 0 9 15.00 0.00 rcu_sched
16時20分35秒 0 398 20.00 0.00 xfsaild/dm-0
16時20分35秒 0 671 1.00 0.00 irqbalance
16時20分35秒 0 1378 1.00 0.00 teamviewerd
16時20分35秒 42 7678 1.00 0.00 gsd-color
16時20分35秒 1003 30259 1.00 0.00 sshd
16時20分35秒 0 30970 3.00 0.00 kworker/0:2
16時20分35秒 0 30995 1.00 0.00 kworker/1:1
16時20分35秒 0 31100 1.00 1.00 pidstat
#從pidstat的輸出可以發現,CPU使用率的升高果然是sysbench導致的,它的CPU使用率已經達到了196%(2核)
#從上面輸出來看,切換次數加起來也就不到一百,比vmstat的73萬明顯小了太多,這是怎麼回事呢?難道是工具本身出了錯嗎?
pidstat
#-t引數表示輸出執行緒的上下文切換指標
[root@local_sa_192-168-1-6 ~]# pidstat -w -t 1
Linux 3.10.0-1160.31.1.el7.x86_64 (local_sa_192-168-1-6) 2021年11月09日 _x86_64_ (2 CPU)
16時28分19秒 UID TGID TID cswch/s nvcswch/s Command
16時28分21秒 0 31143 - 3.00 0.00 kworker/1:2
16時28分21秒 0 - 31143 3.00 0.00 |__kworker/1:2
16時28分21秒 0 31165 - 5.00 0.00 kworker/0:1
16時28分21秒 0 - 31165 5.00 0.00 |__kworker/0:1
16時28分21秒 0 - 31187 14431.00 50613.00 |__sysbench
16時28分21秒 0 - 31188 13076.00 68666.00 |__sysbench
16時28分21秒 0 - 31189 12610.00 53644.00 |__sysbench
16時28分21秒 0 - 31190 11191.00 64400.00 |__sysbench
16時28分21秒 0 - 31191 17173.00 55407.00 |__sysbench
16時28分21秒 0 - 31192 12016.00 44366.00 |__sysbench
16時28分21秒 0 - 31193 12941.00 57103.00 |__sysbench
16時28分21秒 0 - 31194 11404.00 64440.00 |__sysbench
16時28分21秒 0 - 31195 9976.00 60912.00 |__sysbench
16時28分21秒 0 - 31196 16295.00 69772.00 |__sysbench
# 看來,上下文切換罪魁禍首,還是過多的sysbench執行緒
我們已經找到了上下文切換次數增多的根源,那是不是到這兒就可以結束了呢?
當然不是。不知道你還記不記得,前面在觀察系統指標時,除了上下文切換頻率驟然升高,
還有一個指標也有很大的變化。
是的,正是中斷次數。中斷次數也上升到了3萬,
但到底是什麼型別的中斷上升了,現在還不清楚。我們接下來繼續抽絲剝繭找源頭
從/proc/interrupts這個只讀檔案中讀取。
/proc實際上是Linux的一個虛擬檔案系統,用於核心空間與使用者空間之間的通訊。
/proc/interrupts就是這種通訊機制的一部分,提供了一個只讀的中斷使用情況
# -d 高亮顯示變化的區域
[root@local_sa_192-168-1-6 ~]# watch -d cat /proc/interrupts
Every 2.0s: cat /proc/interrupts Tue Nov 9 16:31:48 2021
CPU0 CPU1
......
LOC: 3343255 2547098 Local timer interrupts
SPU: 0 0 Spurious interrupts
PMI: 0 0 Performance monitoring interrupts
IWI: 42561 41437 IRQ work interrupts
RTR: 0 0 APIC ICR read retries
RES: 8119837 8192688 Rescheduling interrupts
......
觀察一段時間,發現變化速度最快的是重排程中斷(RES)
這個中斷型別表示,喚醒空閒狀態的CPU來排程新的任務執行
這是多處理器系統(SMP)中,排程器用來分散任務到不同CPU的機制
通常也被稱為處理器間中斷(Inter-ProcessorInterrupts,IPI)
所以,這裡的中斷升高還是因為過多工的排程問題,跟前面上下文切換次數的分析結果是一致的
小結
每秒上下文切換多少次才算正常呢?
這個數值其實取決於系統本身的CPU效能
如果系統的上下文切換次數比較穩定,那麼從數百到一萬以內,都應該算是正常的
但當上下文切換次數超過一萬次,或者切換次數出現數量級的增長時,就很可能已經出現了效能問題
需要根據上下文切換的型別,再做具體分析。比方說
1.自願上下文切換變多了,說明程序都在等待資源,有可能發生了I/O等其他問題
2.非自願上下文切換變多了,說明程序都在被強制排程,也就是都在爭搶CPU,說明CPU的確成了瓶頸
3.中斷次數變多了,說明CPU被中斷處理程式佔用,還需要通過檢視/proc/interrupts檔案來分析具體的中斷型別
轉載請註明出處喲~ https://www.cnblogs.com/lichengguo