[Linux 性能調優] 網卡中斷與CPU的綁定問題


在Linux的網絡調優方面,如果你發現網絡流量上不去,那么有一個方面需要去查一下:網卡處理網絡請求的中斷是否被綁定到單個CPU(或者說跟處理其它中斷的是同一個CPU)。

先說一下背景

網卡與操作系統的交互一般有兩種方式,

  • 一種是中斷(IRQ,網卡在收到了網絡信號之后,主動發送中斷到CPU,而CPU將會立即停下手邊的活以便對這個中斷信號進行分析),
  • 另一種叫DMA(Direct Memory Access, 也就是允許硬件在無CPU干預的情況下將數據緩存在指定的內存空間內,在CPU合適的時候才處理)

——記得在10多年前開始玩電腦的時候就知道DMA是效率比較高的方式了。但是,這么多年過去了,在網卡方面,大部分還是在用IRQ方式(據說DMA技術僅僅被應用在少數高端網卡上; 另一個說法是:DMA方式會使外部設備的控制器獨占PCI總線,從而CPU無法與外部設備進行交互,這對通用型操作系統Linux來說,是很難接收的,所以DMA方式在Linux內核里使用得很少)。

但是(再來一個但是),在現在的對稱多核處理器(SMP)上,一塊網卡的IRQ還是只有一個CPU來響應,其它CPU無法參與,如果這個CPU還要忙其它的中斷(其它網卡或者其它使用中斷的外設(比如磁盤)),那么就會形成瓶頸。

問題判定

網上不少講這個問題的文章都是直接讓查詢IRQ跟CPU的綁定情況,甚至直接修改。但我們應該先判斷我們的系統是不是受這個問題影響,然后再來看怎么解決。

首先,讓你的網絡跑滿(比如對於MySQL/MongoDB服務,可以通過客戶端發起密集的讀操作; 或者執行一個i大文件傳送任務)

第一個要查明的是:是不是某個CPU在一直忙着處理IRQ?

這個問題我們可以從 mpstat -P ALL 1 的輸出中查明:里面的 %irq 一列即說明了CPU忙於處理中斷的時間占比

18:20:33     CPU   %user   %nice    %sys %iowait    %irq   %soft  %steal   %idle    intr/s
18:20:33     all    0,23    0,00    0,08    0,11    6,41    0,02    0,00   93,16   2149,29
18:20:33       0    0,25    0,00    0,12    0,07    0,01    0,05    0,00   99,49    127,08
18:20:33       1    0,14    0,00    0,03    0,04    0,00    0,00    0,00   99,78      0,00
18:20:33       2    0,23    0,00    0,02    0,03    0,00    0,00    0,00   99,72      0,02
18:20:33       3    0,28    0,00    0,15    0,28   25,63    0,03    0,00   73,64   2022,19

上面的例子中,第四個CPU有25.63%時間在忙於處理中斷(這個數值還不算高,如果高達80%(而同時其它CPU這個數值很低)以上就說明有問題了),后面那個 intr/s 也說明了CPU每秒處理的中斷數(從上面的數據也可以看出,其它幾個CPU都不怎么處理中斷)。

然后我們就要接着查另外一個問題:這個忙於處理中斷的CPU都在處理哪個(些)中斷?

cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
  0:        245          0          0    7134094    IO-APIC-edge  timer
  8:          0          0         49          0    IO-APIC-edge  rtc
  9:          0          0          0          0   IO-APIC-level  acpi
 66:         67          0          0          0   IO-APIC-level  ehci_hcd:usb2
 74:     902214          0          0          0         PCI-MSI  eth0
169:          0          0         79          0   IO-APIC-level  ehci_hcd:usb1
177:          0          0          0    7170885   IO-APIC-level  ata_piix, b4xxp
185:          0          0          0      59375   IO-APIC-level  ata_piix
NMI:          0          0          0          0 
LOC:    7104234    7104239    7104243    7104218 
ERR:          0
MIS:          0

這里記錄的是自啟動以來,每個CPU處理各類中斷的數量(第一列是中斷號,最后一列是對應的設備名)[詳細說明: E.2.10 /proc/interrupts - Deployment Guide - RedHat Enterprise Linux 6 ),從上面可以看到: eth0 所出發的中斷全部都是 CPU0 在處理,而CPU0所處理的中斷請求中,主要是eth0和LOC中斷。(有時我們會看到幾個CPU對同一個中斷類型所處理的的請求數相差無幾(比如上面的LOC一行),這並不一定是說多個CPU會輪流處理同一個中斷,而是因為這里記錄的是“自啟動以來”的統計,中間可能因為irq balancer重新分配過處理中斷的CPU——當然,也可能是誰手工調節過)。

解決問題

首先說明幾點:

  1. 首先應該根據上面的診斷方法查明當前系統是不是受這個原因影響,如果不是,那么就沒有必要往下看了;
  2. 現在的多數Linux系統中已經有了IRQ Balance這個服務(服務程序一般是 /usr/sbin/irqbalance),它可以自動調節分配各個中斷與CPU的綁定關系,以避免所有中斷的處理都集中在少數幾個CPU上;
  3. 在某些情況下,這個IRQ Balance反而會導致問題,會出現 irqbalance 這個進程反而自身占用了較高的CPU(當然也就影響了業務系統的性能)[參考: mongodb性能問題及原理分析 ]

下面來說手工將中斷限定到少數幾個CPU的方法。

首先當然要查明,該網卡的中斷當前是否已經限定到某些CPU了?具體是哪些CPU?

根據上面 /proc/interrupts 的內容我們可以看到 eth0 的中斷號是74,然后我們來看看該中斷號的CPU綁定情況(或者說叫親和性 affinity)

$ sudo cat /proc/irq/74/smp_affinity
ffffff

這個輸出是一個16進制的數值,0xffffff = ‘0b111111111111111111111111’,這就意味着這里有24個CPU,所有位都為1表示所有CPU都可以被該中斷干擾。

另一個例子:

$ sudo cat /proc/irq/67/smp_affinity
00000001

這個例子說明,只有CPU0處理編號為67的中斷。

修改配置的方法

我們可以用 echo 2 > /proc/irq/74/smp_affinity 的方法來修改這個設置(設置為2表示將該中斷綁定到CPU1上,0x2 = 0b10,而第一個CPU為CPU0)

參考


免責聲明!

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



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