2.2 CPU 上下文切换是什么意思?(下)
怎么查看系統(tǒng)的上下文切換情況
過多的上下文切換,會把 CPU 時間消耗在寄存器、內(nèi)核棧以及虛擬內(nèi)存等數(shù)據(jù)的保存和恢復(fù)上,縮短進(jìn)程真正運(yùn)行的時間,成了系統(tǒng)性能大幅下降的一個 元兇。
使用 vmstat 這個工具,來查詢系統(tǒng)的上下文切換情況。
vmstat 是一個常用的系統(tǒng)性能分析工具,主要用來分析系統(tǒng)的內(nèi)存使用情況,也常用來分析 CPU 上下文切換和中斷的次數(shù)。
vmstat 的使用示例:
???? vmstat 只給出了系統(tǒng)總體的上下文切換情況,要想查看每個進(jìn)程的詳細(xì)情況,就需要使用我們前面提到過的 pidstat 了。給它加上 -w 選項(xiàng),你就可以查看每個進(jìn)程上下文切換的情況了。
每隔 5 秒輸出 1 組數(shù)據(jù) [root@doit ~]# pidstat -w 5 Linux 4.20.0-1.el7.elrepo.x86_64 (doit) 07/12/2019 _x86_64_ (2 CPU)04:28:40 PM UID PID cswch/s nvcswch/s Command04:28:45 PM 0 9 0.20 0.00 ksoftirqd/004:28:45 PM 0 10 2.00 0.00 rcu_sched04:28:45 PM 0 11 0.40 0.00 migration/004:28:45 PM 0 15 0.40 0.00 migration/104:28:45 PM 0 27 0.20 0.00 khugepaged04:28:45 PM 0 3086 0.20 0.00 haveged04:28:45 PM 0 3104 9.98 0.00 qemu-ga04:28:45 PM 0 3492 1.00 0.00 httpd04:28:45 PM 0 6094 0.40 0.00 python04:28:45 PM 0 29541 5.39 0.00 kworker/1:0-events_power_efficient04:28:45 PM 0 29590 1.40 0.00 kworker/0:1-events04:28:45 PM 0 29716 0.20 0.20 pidstat一個是 cswch ,表示每秒自愿上下文切換(voluntary context switches)的次數(shù),另一個則是 nvcswch ,表示每秒非自愿上下文切換(non voluntary context switches)的次數(shù)。所謂自愿上下文切換,是指進(jìn)程無法獲取所需資源,導(dǎo)致的上下文切換。比如說, I/O、內(nèi)存等系統(tǒng)資源不足時,就會發(fā)生自愿上下文切換。
而非自愿上下文切換,則是指進(jìn)程由于時間片已到等原因,被系統(tǒng)強(qiáng)制調(diào)度,進(jìn)而發(fā)生的上下文切換。比如說,大量進(jìn)程都在爭搶 CPU 時,就容易發(fā)生非自愿上下文切換。
案例分析
上下文切換頻率是多少次才算正常呢?
sysbench? 是一個多線程的基準(zhǔn)測試工具,一般用來評估不同系統(tǒng)參數(shù)下的數(shù)據(jù)庫負(fù)載情況。當(dāng)然,在這次案例中,我們只把它當(dāng)成一個異常進(jìn)程來看,作用是模擬上下文切換過多的問題。
預(yù)先安裝 sysbench 和 sysstat 包,如 apt install sysbench sysstat
操作和分析
首先,在第一個終端里運(yùn)行 sysbench ,模擬系統(tǒng)多線程調(diào)度的瓶頸:
# 以 10 個線程運(yùn)行 5 分鐘的基準(zhǔn)測試,模擬多線程切換的問題 [root@doit ~]# sysbench --threads=10 --max-time=300 threads run WARNING: --max-time is deprecated, use --time instead sysbench 1.0.17 (using system LuaJIT 2.0.4)Running the test with following options: Number of threads: 10 Initializing random number generator from current timeInitializing worker threads...Threads started!
在第二個終端運(yùn)行 vmstat ,觀察上下文切換情況:
綜合這幾個指標(biāo),我們可以知道,系統(tǒng)的就緒隊(duì)列過長,也就是正在運(yùn)行和等待 CPU 的進(jìn)程數(shù)過多,導(dǎo)致了大量的上下文切換,而上下文切換又導(dǎo)致了系統(tǒng) CPU 的占用率升高。
那么到底是什么進(jìn)程導(dǎo)致了這些問題呢?
在第三個終端再用 pidstat 來看一下, CPU 和進(jìn)程上下文切換的情況
# 每隔 1 秒輸出 1 組數(shù)據(jù)-w 參數(shù)表示輸出進(jìn)程切換指標(biāo),而 -u 參數(shù)則表示輸出 CPU 使用指標(biāo)[root@doit ~]# pidstat -w -u 1Linux 4.20.0-1.el7.elrepo.x86_64 (doit) 07/12/2019 _x86_64_ (2 CPU)04:38:35 PM UID PID %usr %system %guest %wait %CPU CPU Command04:38:36 PM 0 29730 33.00 167.00 0.00 0.00 200.00 0 sysbench04:38:35 PM UID PID cswch/s nvcswch/s Command04:38:36 PM 0 10 3.00 0.00 rcu_sched04:38:36 PM 0 16 1.00 0.00 ksoftirqd/104:38:36 PM 0 3104 10.00 0.00 qemu-ga04:38:36 PM 0 3492 1.00 0.00 httpd04:38:36 PM 0 29541 14.00 0.00 kworker/1:0-events_power_efficient04:38:36 PM 0 29590 2.00 0.00 kworker/0:1-mm_percpu_wq04:38:36 PM 0 29640 1.00 0.00 sshd04:38:36 PM 0 29714 1.00 0.00 kworker/u4:0-events_unbound04:38:36 PM 0 29742 1.00 0.00 pidstat 從 pidstat 的輸出你可以發(fā)現(xiàn),CPU 使用率的升高果然是 sysbench 導(dǎo)致的,它的 CPU 使用率已經(jīng)達(dá)到了 200%。但上下文切換則是來自其他進(jìn)程,自愿上下文切換頻率最高的內(nèi)核線程 kworker。pidstat 輸出的上下文切換次數(shù),加起來也就幾百,比 vmstat 的 139 萬明顯小了太多。這是怎么回事呢?難道是工具本身出了錯嗎?
pidstat 默認(rèn)顯示進(jìn)程的指標(biāo)數(shù)據(jù),加上 -t 參數(shù)后, 才會輸出線程的指標(biāo)。
[root@doit ~]# pidstat -wt 1 Linux 4.20.0-1.el7.elrepo.x86_64 (doit) 07/12/2019 _x86_64_ (2 CPU)04:45:02 PM UID TGID TID cswch/s nvcswch/s Command04:45:03 PM 0 9 - 2.91 0.00 ksoftirqd/004:45:03 PM 0 - 9 2.91 0.00 |__ksoftirqd/004:45:03 PM 0 10 - 10.68 0.00 rcu_sched04:45:03 PM 0 - 10 10.68 0.00 |__rcu_sched04:45:03 PM 0 16 - 0.97 0.00 ksoftirqd/104:45:03 PM 0 - 16 0.97 0.00 |__ksoftirqd/104:45:03 PM 0 3104 - 9.71 0.00 qemu-ga04:45:03 PM 0 - 3104 9.71 0.00 |__qemu-ga04:45:03 PM 0 - 3820 0.97 0.00 |__tuned04:45:03 PM 0 6094 - 0.97 0.00 python04:45:03 PM 0 - 6094 0.97 0.00 |__python04:45:03 PM 0 - 14238 0.97 0.00 |__node04:45:03 PM 0 29590 - 1.94 0.00 kworker/0:1-mm_percpu_wq04:45:03 PM 0 - 29590 1.94 0.00 |__kworker/0:1-mm_percpu_wq04:45:03 PM 0 - 29768 20572.82 100301.94 |__sysbench04:45:03 PM 0 - 29769 18718.45 110695.15 |__sysbench04:45:03 PM 0 - 29770 22306.80 104282.52 |__sysbench04:45:03 PM 0 - 29771 26055.34 86372.82 |__sysbench04:45:03 PM 0 - 29772 20498.06 102583.50 |__sysbench04:45:03 PM 0 - 29773 14956.31 81900.00 |__sysbench04:45:03 PM 0 - 29774 29092.23 112430.10 |__sysbench04:45:03 PM 0 - 29775 24825.24 110958.25 |__sysbench04:45:03 PM 0 - 29776 23862.14 95394.17 |__sysbench04:45:03 PM 0 - 29777 21125.24 87931.07 |__sysbench04:45:03 PM 0 29780 - 12.62 0.00 kworker/1:1-events_power_efficient04:45:03 PM 0 - 29780 12.62 0.00 |__kworker/1:1-events_power_efficient04:45:03 PM 0 29783 - 0.97 1.94 pidstat04:45:03 PM 0 - 29783 0.97 1.94 |__pidstat? 雖然 sysbench 進(jìn)程(也就是主線程)的上下文切換次數(shù)看起來并不多,但它的子線程的上下文切換次數(shù)卻有很多。看來,上下文切換罪魁禍?zhǔn)?#xff0c;還是過多的sysbench 線程。
?? 在觀察系統(tǒng)指標(biāo)時,除了上下文切換頻率驟然升高,還有一個指標(biāo)也有很大的變化。是的,正是中斷次數(shù)。中斷次數(shù)也上升到了 1 萬,但到底是什么類型的中斷上升了,現(xiàn)在還不清楚。接下來繼續(xù)抽絲剝繭找源頭。既然是中斷,我們都知道,它只發(fā)生在內(nèi)核態(tài),而 pidstat 只是一個進(jìn)程的性能分析工具,并不提供任何關(guān)于中斷的詳細(xì)信息,怎樣才能知道中斷發(fā)生的類型呢?
沒錯,那就是從 /proc/interrupts 這個只讀文件中讀取。/proc 實(shí)際上是 Linux 的一個虛擬文件系統(tǒng),用于內(nèi)核空間與用戶空間之間的通信。/proc/interrupts? 就是這種通信機(jī)制的一部分,提供了一個只讀的中斷使用情況。
[root@doit ~]# watch -d cat /proc/interruptsEvery 2.0s: cat /proc/interrupts Fri Jul 12 16:49:08 2019CPU0 CPU1LOC: 83008310 107586288 Local timer interruptsSPU: 0 0 Spurious interruptsPMI: 0 0 Performance monitoring interruptsIWI: 0 1 IRQ work interruptsRTR: 0 0 APIC ICR read retriesRES: 9169892 7079828 Rescheduling interrupts???? 觀察一段時間,你可以發(fā)現(xiàn),變化速度最快的是重調(diào)度中斷(RES),這個中斷類型表示,喚醒空閑狀態(tài)的 CPU 來調(diào)度新的任務(wù)運(yùn)行。這是多處理器系統(tǒng)(SMP)中,調(diào)度器用來分散任務(wù)到不同 CPU 的機(jī)制,通常也被稱為處理器間中斷(Inter-Processor Interrupts,IPI)。所以,這里的中斷升高還是因?yàn)檫^多任務(wù)的調(diào)度問題,跟前面上下文切換次數(shù)的分析結(jié)果是一致的。
現(xiàn)在再回到最初的問題,每秒上下文切換多少次才算正常呢?
???? 這個數(shù)值其實(shí)取決于系統(tǒng)本身的 CPU 性能。在我看來,如果系統(tǒng)的上下文切換次數(shù)比較穩(wěn)定,那么從數(shù)百到一萬以內(nèi),都應(yīng)該算是正常的。但當(dāng)上下文切換次數(shù)超過一萬次,或者切換次數(shù)出現(xiàn)數(shù)量級的增長時,就很可能已經(jīng)出現(xiàn)了性能問題。
這時,你還需要根據(jù)上下文切換的類型,再做具體分析。比方說:
??? 自愿上下文切換變多了,說明進(jìn)程都在等待資源,有可能發(fā)生了 I/O 等其他問題;
??? 非自愿上下文切換變多了,說明進(jìn)程都在被強(qiáng)制調(diào)度,也就是都在爭搶 CPU,說明 CPU 的確成了瓶頸;
??? 中斷次數(shù)變多了,說明 CPU 被中斷處理程序占用,還需要通過查看 /proc/interrupts 文件來分析具體的中斷類型。
小結(jié)
通過一個 sysbench 的案例,給你講了上下文切換問題的分析思路。碰到上下文切換次數(shù)過多的問題時,我們可以借助 vmstat 、 pidstat 和 /proc/interrupts 等工具,來輔助排查性能問題的根源。
首先通過uptime查看系統(tǒng)負(fù)載,然后使用mpstat結(jié)合pidstat來初步判斷到底是cpu計(jì)算量大還是進(jìn)程爭搶過大或者是io過多,接著使用vmstat分析切換次數(shù),以及切換類型,來進(jìn)一步判斷到底是io過多導(dǎo)致問題還是進(jìn)程爭搶激烈導(dǎo)致問題。
總結(jié)
以上是生活随笔為你收集整理的2.2 CPU 上下文切换是什么意思?(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2.1 CPU 上下文切换(上)
- 下一篇: 3 当某个应用的CPU使用达到100%,