Linux性能優化實戰學習筆記:第四講


一、怎么查看系統上下文切換情況

通過前面學習我么你知道,過多的上下文切換,會把CPU時間消耗在寄存器、內核棧以及虛擬內存等數據的保存和回復上,縮短進程
真正運行的時間,成了系統性能大幅下降的一個元凶

既然上下文切換對系統性能影響那么大,你肯定迫不及待想知道,道題怎么查看上下文切換

 1、系統總的上下文切換情況

[root@nfs ~]# 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
 1  0  45668 1600548      0 341196   27  109   131   112  239  280  4 17 79  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   33   44  0  0 100  0  0
 1  0  45668 1600556      0 341196    0    0     0     0   31   39  0  0 100  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   50   48  1  1 99  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   31   42  0  0 100  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   32   41  0  1 100  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   32   38  0  0 100  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   29   37  0  0 100  0  0
 0  0  45668 1600556      0 341196    0    0     0     0   29   38  0  0 100  0  0

 2、每個進程的上下文切換情況

可以看到這個例子中的上下文切換cs是280次,而系統中斷次數in則是239次,而就緒隊列長度r和不可中斷狀態是1進程數b都是0

只給出了系統總的上下文切換情況,要想查看每個進程的上下文切換的情況了?

$ 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

 UID       PID   cswch/s nvcswch/s  Command
   0         8     11.00      0.00  rcu_sched
   0        16      1.00      0.00  ksoftirqd/1
   0       471      1.00      0.00  hv_balloon
   0      1230      1.00      0.00  iscsid
   0      4089      1.00      0.00  kworker/1:5
   0      4333      1.00      0.00  kworker/0:3
   0     10499      1.00    224.00  pidstat
   0     26326    236.00      0.00  kworker/u4:2
1000     26784    223.00      0.00  ssh

 

3、什么是自願上下文切換

所謂自願上下文切換,是指進程無法獲取所需自願,導致的上下文奇幻。比如比如說, I/O、內存等系統資源不足時,就會發生自願上下文切...是

4、什么是非自願上下文切換

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

二、案例分析

1、分析環境

機器配置:2 CPU,4GB 內存

預先安裝 sysbench

cnetos 7.2

curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
yum -y install sysbench  

三、分析操作

終端一

# 以 10 個線程運行 5 分鍾的基准測試,模擬多線程切換的問題
$ sysbench --threads=10 --max-time=300 threads run

終端二

# 每隔 1 秒輸出 1 組數據(需要 Ctrl+C 才結束)
[root@nfs ~]# 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
 6  0  45412 1585156      0 351460   10   38    46    39  118   10  2  8 90  0  0
 8  0  45412 1585156      0 351468    0    0     0     0 2023 2208584 17 83  0  0  0
 7  0  45412 1585156      0 351468    0    0     0     0 2008 2183632 18 82  1  0  0
 8  0  45412 1585156      0 351468    0    0     0     0 2013 2278429 17 83  0  0  0
 8  0  45412 1585156      0 351468    0    0     0     0 2008 2251628 18 82  0  0  0
 6  0  45412 1585156      0 351468    0    0     0     0 2014 2236468 19 81  0  0  0
 7  0  45412 1585156      0 351468    0    0     0     0 2004 2255035 17 83  0  0  0
 6  0  45412 1585156      0 351468    0    0     0     0 2020 2212782 18 82  1  0  0
 7  0  45412 1585156      0 351468    0    0     0     0 2013 2194160 19 81  0  0  0

你應該可以發現,cs列的上下文切換次數從之前的10驟然上升了220萬,同時,注意觀察其他幾個指標

r 列:就緒隊列的長度已經到了 8,遠遠超過了系統 CPU的個數2,所以肯定會有大量的CPU競爭

us(user)和 sy(system)列:這兩列的 CPU使用率加起來上升到了 100%,其中系統CPU使用率,也就是sy列高達90%說明CPU主要被內核占用了

in 列:中斷次數也上升到了 1 萬左右,說明中斷處理也是個潛在的問題

綜合這幾個指標,我們可以知道,系統的就緒隊列過長,也就是正在運行和等待的CPU進程數過多,導致大量的上下文切換,而上下文切換還又導致了系統CPU的占用率升高

終端三

那么到底是是哪個進程導致了這些問題了

[root@nfs ~]# pidstat -w -u 1
Linux 3.10.0-957.12.1.el7.x86_64 (nfs) 	05/03/2019 	_x86_64_	(2 CPU)

12:58:57 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
12:58:59 PM     0      9183   31.07  162.14    0.00    0.00  193.20     0  sysbench
12:58:59 PM     0      9196    0.00    0.97    0.00    0.00    0.97     0  kworker/0:0

12:58:57 PM   UID       PID   cswch/s nvcswch/s  Command
12:58:59 PM     0         3      1.94      0.00  ksoftirqd/0
12:58:59 PM     0         9      7.77      0.00  rcu_sched
12:58:59 PM     0       103      1.94      0.00  kworker/1:2
12:58:59 PM     0      5823     10.68      0.00  vmtoolsd
12:58:59 PM     0      6969      0.97      0.00  sshd
12:58:59 PM     0      9066      0.97      0.00  kworker/u256:1
12:58:59 PM     0      9195      0.97      0.00  vmstat
12:58:59 PM     0      9196      1.94      0.00  kworker/0:0
12:58:59 PM     0      9198      0.97      0.00  pidstat
^C

從 pidstat 的輸出你可以發現,CPU 使用率的升高果然是 sysbench 導致的,它的 CPU 使用率已經達到了 100%但是上下文切換則是來自其他進程,包括非自願上下文切換頻率最高的pidstat

以及自願上下文切換頻率最高的內核線程kworker 和 sshd

不過,細心的你肯定也發現了一個怪異的事兒:pidstat 出的上下文切換次數,加起來也就幾百,比 vmstat 的 220萬明顯小了太多。這是怎么回事呢?難道是工具本身出了錯嗎?

通過運行 man pidstat ,你會發現,pidstat默認顯示進程的指標數據,加上 -t 參數后,才會輸出線程的指標

我們還是在第三個終端里, Ctrl+C 停止剛才的 pidstat 命令,然后運行下面的命令,觀察中斷的變化情況.

[root@nfs ~]# pidstat -wt 1
Linux 3.10.0-957.12.1.el7.x86_64 (nfs) 	05/03/2019 	_x86_64_	(2 CPU)

01:00:35 PM   UID      TGID       TID   cswch/s nvcswch/s  Command
01:00:36 PM     0         3         -      0.93      0.00  ksoftirqd/0
01:00:36 PM     0         -         3      0.93      0.00  |__ksoftirqd/0
01:00:36 PM     0         9         -     17.76      0.00  rcu_sched
01:00:36 PM     0         -         9     17.76      0.00  |__rcu_sched
01:00:36 PM     0        14         -      3.74      0.00  ksoftirqd/1
01:00:36 PM     0         -        14      3.74      0.00  |__ksoftirqd/1
01:00:36 PM     0       103         -      1.87      0.00  kworker/1:2
01:00:36 PM     0         -       103      1.87      0.00  |__kworker/1:2
01:00:36 PM     0      5823         -     10.28      0.00  vmtoolsd
01:00:36 PM     0         -      5823     10.28      0.00  |__vmtoolsd
01:00:36 PM     0         -      6755      0.93      0.00  |__tuned
01:00:36 PM     0         -      6666      0.93      0.00  |__in:imjournal
01:00:36 PM     0      6969         -      0.93      0.00  sshd
01:00:36 PM     0         -      6969      0.93      0.00  |__sshd
01:00:36 PM     0      9066         -      0.93      0.00  kworker/u256:1
01:00:36 PM     0         -      9066      0.93      0.00  |__kworker/u256:1
01:00:36 PM     0         -      9184  37752.34 157714.02  |__sysbench
01:00:36 PM     0         -      9185  43673.83 153500.00  |__sysbench
01:00:36 PM     0         -      9186  32598.13 150383.18  |__sysbench
01:00:36 PM     0         -      9187  31631.78 179364.49  |__sysbench
01:00:36 PM     0         -      9188  43047.66 129503.74  |__sysbench
01:00:36 PM     0         -      9189  25115.89 170748.60  |__sysbench
01:00:36 PM     0         -      9190  40545.79 179413.08  |__sysbench
01:00:36 PM     0         -      9191  48101.87 157711.21  |__sysbench
01:00:36 PM     0         -      9192  31725.23 164217.76  |__sysbench
01:00:36 PM     0         -      9193  37538.32 159869.16  |__sysbench
01:00:36 PM     0      9195         -      0.93      0.00  vmstat
01:00:36 PM     0         -      9195      0.93      0.00  |__vmstat
01:00:36 PM     0      9196         -      1.87      0.00  kworker/0:0
01:00:36 PM     0         -      9196      1.87      0.00  |__kworker/0:0
01:00:36 PM     0      9200         -      0.93      0.93  pidstat
01:00:36 PM     0         -      9200      0.93      0.93  |__pidstat

現在你就能看到了,雖然 sysbench 進程(也就是主線程)的上下文切換次數看起來並不多,但它的子線程的上下文切換粗疏卻又很多,

看來,上下文切換醉魁禍首,還是過多的線程

[root@nfs ~]# tail -15 /proc/interrupts
 IWI:       6600       5405   IRQ work interrupts
 RTR:          0          0   APIC ICR read retries
 RES:      22360      25295   Rescheduling interrupts
 CAL:       1158        647   Function call interrupts
 TLB:      23862       8639   TLB shootdowns
 TRM:          0          0   Thermal event interrupts
 THR:          0          0   Threshold APIC interrupts
 DFR:          0          0   Deferred Error APIC interrupts
 MCE:          0          0   Machine check exceptions
 MCP:         35         35   Machine check polls
 ERR:          0
 MIS:          0
 PIN:          0          0   Posted-interrupt notification event
 NPI:          0          0   Nested posted-interrupt event
 PIW:          0          0   Posted-interrupt wakeup event

觀察一段時間,你可以發現,變化速度最快的是重調度中斷,這中斷類似表示,喚醒空閑狀態的CPU來調度新的任務運行,這是多處理器中,調度器用來分散任務到不同CPU的機制,通常也被稱為處理間中斷

cswch過多說明資源IO問題,nvcswch過多說明調度爭搶cpu過多,中斷次數變多說明cpu被中斷程序調用

四、小結

1、每秒上下文奇幻多少次才算正常呢?

這個數值其實取決於系統本身的CPU性能,在我看來,如果系統上下文切換次數比較穩定,那么從數百一萬以內,都有應該算是正常的,

但當上下文奇幻次數超過一萬次,或者切換次數出現數量級的增長時,就很可能已經出現性能問題

2、根據上下文切換類型再具體分析

自願上下文切換變多了,說明進程都在等待自願,有可能發生了I/O等其他問題;

非自願上下文切換變多了,說明進程都在被強制調動,也就是在爭搶CPU,說明CPU的確成了瓶頸

中斷次數變多了了,說明CPU被中斷處理程序占用,還需要通過查看/proc/interrupts 文件來分析具體的中斷類型。

3、假設我現在有一台Linux服務器負載變高了,如何找到原因?如何排查分析

Step1: 首先通過uptime看下最近一段時間的負載怎么樣,能夠得出是徒然變高還是變高已經有一段時間了,比較5min和15min系統負載的數據

Step2: 分析系統負載高的原因有哪些?根據前面學習的,可能是計算密集型任務導致,IO密集型任務導致,還有可能是大量線程等待調度導致,還有可能是幾種情況的組合同時存在。這里要怎么分析可以通過mpstat工具來區分,主要關注的幾個指標是%idle %iowait %wait

Step3: 如果通過上一步確認是大量線程等待調度導致,那么可以通過vmstat來查看系統整體的上下文切換情況,主要關注cs/in/r/b 四個指標

Step4: 我們已經知道了系統負載高的原因,進一步通過pidstat 查看具體是那一個線程導致的詳細原因

4、拍錯思路總結

登錄到服務器,現在系統負載怎么樣 。 高的話有三種情況,首先是cpu使用率 ,其次是io使用率 ,之后就是兩者都高 。

cpu 使用率高,可能確實是使用率高, 也的可能實際處理不高而是進程太多切換上下文頻繁 , 也可能是進程內線程的上下文切換頻繁

io 使用率高 , 說明 io 請求比較大, 可能是 文件io 、 網絡io 。

工具 :
系統負載 : uptime ( watch -d uptime)看三個階段平均負載

系統整體情況 : mpstat (mpstat -p ALL 3) 查看 每個cpu當前的整體狀況,可以重點看用戶態、內核態、以及io等待三個參數

系統整體的平均上下文切換情況 : vmstat (vmstat 3) 可以重點看 r (進行或等待進行的進程)、b (不可中斷進程/io進程) 、in (中斷次數) 、cs(上下文切換次數)

查看詳細的上下文切換情況 : pidstat (pidstat -w(進程切換指標)/-u(cpu使用指標)/-wt(線程上下文切換指標)) 注意看是自願上下文切換、還是被動上下文切換

io使用情況 : iostat


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM