1. 程式人生 > 其它 >04-基礎篇:經常說的 CPU 上下文切換是什麼意思?(下)

04-基礎篇:經常說的 CPU 上下文切換是什麼意思?(下)





怎麼檢視系統的上下文切換情況

過多的上下文切換,會把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