軟中斷會吃掉你多少CPU?

軟中斷會吃掉你多少CPU?

前面的幾篇文章裡討論過了進程上下文切換和系統調用對系統性能的影響,我們今天再來看另外一個CPU吃貨,那就是軟中斷。

你在用vmstat或者其他一些工具查看系統CPU消耗的時候,發現有兩列是單獨列出來的,分別是是hi和si。他們分別是硬中斷和軟中斷。既然vmstat把中斷的開銷單獨列出來了,就說明一個問題,中斷吃起CPU來那也是絲毫不含糊。

我們沒必要啃明白軟中斷的所有原理,但從一名追求性能的開發者的角度來看,我們有必要了解以下問題:

  • 一次軟中斷的開銷到底多大?
  • 你的服務器上被軟中斷吃掉了多少CPU時間?

如果你和我一樣好奇上面的問題的答案,那請跟我來!

一、軟中斷的誕生

CPU正常情況下都是專心處理用戶的進程的,當外部的硬件或軟件有消息想要通知CPU,就會通過

中斷請求(interrupt request,IRQ)的方式來進行。比如當你的鼠標有了點擊產生,再比如磁盤設備完成了數據的讀取的時候,都會通過中斷通知CPU工作已完成。

但是當中斷機制應用到網絡IO的時候,就產生了一點點問題。網絡包收到後的處理工作,不像鼠標、鍵盤、磁盤IO讀取完成那樣簡單,而是要進行大量的內核協議棧的處理,最終才能放到進程的接收緩存區中。假如只用一種中斷(硬終端)的方式來處理網絡IO,由於硬中斷的優先級又比較高,這樣CPU就會忙於處理大量的網絡IO而不能及時響應鍵盤鼠標等事情,導致操作系統實時性變差,你會感覺機器以卡一卡的。

所以現代的Linux又發明了軟件中斷,配合硬中斷來處理網絡IO。 硬中斷你可以理解只是個收包的,把包收取回來放到“家裡”就完事,很快就能完成,這樣不耽誤CPU響應其它外部高優先級的中斷。而軟中斷優先級較低,負責將包進行各種處理,完成從驅動層、到網絡協議棧,最終把處理出來的數據放到socker的接收buffer中。

軟中斷消耗的CPU週期相對比硬中斷要多不少,所以我們本文來重點關注軟中斷的開銷。

二、軟中斷開銷估算

前面大致介紹了軟中斷的來龍去脈,好了直接進入本文的主題上,軟中斷開銷到底多大。好了,請跟我來一起計算:

1) 查看軟中斷總耗時

首先用top命令可以看出每個核上軟中斷的開銷佔比,是在si列

top
top - 19:51:24 up 78 days, 7:53, 2 users, load average: 1.30, 1.35, 1.35
Tasks: 923 total, 2 running, 921 sleeping, 0 stopped, 0 zombie
Cpu(s): 7.1%us, 1.4%sy, 0.0%ni, 90.1%id, 0.1%wa, 0.2%hi, 1.2%si, 0.0%st
Mem: 65872372k total, 64711668k used, 1160704k free, 339384k buffers
Swap: 0k total, 0k used, 0k free, 55542632k cached

如上圖所示,CPU大約花費了1.2%的時鐘週期在軟中斷上,也就是說每個核要花費12ms。

2)查看軟中斷次數

再用vmstat命令可以看到軟中斷的次數

$ 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 0 1231716 339244 55474204 0 0 6 496 0 0 7 3 90 0 0
2 0 0 1231352 339244 55474204 0 0 0 128 57402 24593 5 2 92 0 0
2 0 0 1230988 339244 55474528 0 0 0 140 55267 24213 5 2 93 0 0
2 0 0 1230988 339244 55474528 0 0 0 332 56328 23672 5 2 93 0 0

每秒大約有56000次左右的軟中斷(該機器上是web服務,網絡IO密集型的機器,其它中斷可以忽略不計)。

3)計算每次軟中斷的耗時

該機器是16核的物理實機,故可以得出每個軟中斷需要的CPU時間是=12ms/(56000/16)次=3.428us

從實驗數據來看,一次軟中斷CPU開銷大約3.4us左右

三、軟中斷的上下文切換

前文我們計算出了一個相對比較精確的開銷時間。這個時間裡其實包含兩部分,一是上下文切換開銷,二是軟中斷內核執行開銷。 其中上下文切換和系統調用、進程上下文切換有很多相似的地方。讓我們將他們進行一個簡單的對比:

1)和系統調用開銷對比

《深入理解Linux內核-第五章》開頭的一句話,很形象地把中斷和系統調用兩個不相關的概念聯繫了起來,巧妙地找到了這二者之間的相似處。“你可以把內核看做是不斷對請求進行響應的服務器,這些請求可能來自在CPU上執行的進程,也可能來自發出中斷的外部設備。老闆的請求相當於中斷,而顧客的請求相當於用戶態進程發出的系統調用”。

軟中斷和系統調用一樣,都是CPU停止掉當前用戶態上下文,保存工作現場,然後陷入到內核態繼續工作。二者的唯一區別是系統調用是切換到同進程的內核態上下文,而軟中斷是則是切換到了另外一個內核進程ksoftirqd上。

而事實上,早期的系統調用也還真的是通過彙編指令int(中斷)來實現的,當用戶態進程發出int $0x80指令時,CPU切換到內核態並開始執行system_call函數。後來大家覺得系統調用實在是太慢了,因為int指令要執行一致性和安全性檢查。後來內核又該用了Intel提供的“快速系統調用”的sysenter指令,才算是和中斷脫離了一點點干係。而軟中斷必須得進行這些檢查,所以從這點上來看,中斷的開銷應該是比系統調用的開銷要多的。

根據前文的實驗結果,系統調用開銷是200ns起步。沒看過這個文章的同學可以關注我,然後從歷史文章裡找。

2)和進程上下文切換開銷對比

和進程上下文切換比較起來,進程上下文切換是從用戶進程A切換到了用戶進程B。而軟中斷切換是從用戶進程A切換到了內核線程ksoftirqd上。 而ksoftirqd作為一個內核控制路徑,其處理程序比一個用戶進程要輕量,所以上下文切換開銷相對比進程切換要稍一些。大家感興趣的,可以繼續閱讀《深入理解Linux內核》的-第五章。

根據前文的實驗結果,進程上下文切換開銷是3us-5us。沒看過這個文章的同學可以關注我,然後從歷史文章裡找。

相關Linux命令

  • top: si列展示軟中斷造成CPU開銷
  • vmstat 1:in列每秒展示軟中斷次數
  • cat /proc/softirqs:展示所有軟中斷髮生的總數,包括TIMER、NET_TX、NET_RX等

參考文獻

  • [深入理解Linux內核]


分享到:


相關文章: