中断优化

如何优化软中断 CPU0 过高问题

RSS(Receive Side Scaling,需网卡支持多队列)

查看网卡是否支持队列

root@geekwolf:~# lscpi -vvv
06:00.0 Ethernet controller: Broadcom Corporation BCM57840 NetXtreme II 10/20-Gigabit Ethernet (rev 11)
 Subsystem: Hewlett-Packard Company Device 22fa
 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
 Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <tabort - <MAbort- >SERR- <perr - INTx-
 Latency: 0, Cache Line Size: 64 bytes
 Interrupt: pin A routed to IRQ 32
 Region 0: Memory at 93800000 (64-bit, prefetchable) [size=8M]
 Region 2: Memory at 93000000 (64-bit, prefetchable) [size=8M]
 Region 4: Memory at 95000000 (64-bit, prefetchable) [size=64K]
 [virtual] Expansion ROM at 95080000 [disabled] [size=512K]
 Capabilities: [48] Power Management version 3
   Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
   Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=1 PME-
 Capabilities: [50] Vital Product Data
   Product Name: HP FlexFabric 10Gb 2-port 536FLB Adapter
   Read-only fields:
     [PN] Part number: 766488-001
     [EC] Engineering changes: A-5444
     [MN] Manufacture ID: 31 30 33 43
     [V0] Vendor specific: 12W PCIeGen3
     [V1] Vendor specific: 7.10.55
     [V3] Vendor specific: 7.10.72
     [V5] Vendor specific: 0A
     [V6] Vendor specific: 7.10.72
     [V7] Vendor specific: 536FLB
     [SN] Serial number: 7C444703LG
     [V2] Vendor specific: 5447
     [V4] Vendor specific: 8CDCD419D870
     [RV] Reserved: checksum good, 186 byte(s) reserved
   End
  : [a0] MSI-X: Enable+ Count=32 Masked-

找到 Ethernet controller 项,如果有 MSI-X,Enable+ 并且 Count>1,表示该网卡支持多队列

查看网卡支持多少个队列

~]# grep eth0 /proc/interrupts |awk '{print $NF}'
eth0
eth0-fp-0
eth0-fp-1
eth0-fp-2
eth0-fp-3
eth0-fp-4
eth0-fp-5
eth0-fp-6
eth0-fp-7

配置 SMP IRQ affinity

(即绑定队列到不同 CPU,Kernel>2.4)

方法 1:开启系统 irqbalance 服务

apt-get -y install irqbalanceservice irqbalance start

方法 2: 手动绑定

/proc/irq/:该目录下存放的是以IRQ号命名的目录,如/proc/irq/40/,表示中断号为40的相关信息
/proc/irq/[irq_num]/smp_affinity:该文件存放的是CPU位掩码(十六进制)。修改该文件中的值可以改变CPU和某中断的亲和性
/proc/irq/[irq_num]/smp_affinity_list:该文件存放的是CPU列表(十进制)。注意,CPU核心个数用表示编号从0开始,如cpu0,cpu1等,

smp_affinity和smp_affinity_list修改其一即可,下面修改smp_affinity:

echo $bitmask > /proc/irq/IRQ#/smp_affinity
示例(把140号中断绑定到前4个CPU[cpu0-3]上面):
echo  f >/proc/irq/140/smp_affinity

CPU 位掩码计算

一个十六进制 f 转换成二进制为 1111,每一位表示一个 CPU 核,最靠右值是最低位即 CPU0

           Binary       Hex
   CPU 0    0001         1
   CPU 1    0010         2
   CPU 2    0100         4
   CPU 3    1000         8
   其中十六进制2就表示CPU1,十六进制8就表示CPU3


           Binary       Hex
   CPU 0    0001         1
 + CPU 2    0100         4
   -----------------------
   both     0101         5
   其中得出的十六进制和5表示CPU0 和CPU2


           Binary       Hex
   CPU 0    0001         1
   CPU 1    0010         2
   CPU 2    0100         4
 + CPU 3    1000         8
   -----------------------
   both     1111         f
   4个CPU参与中断,即可设置为f,8个CPU参与中断可设置为ff,以此类推

配置 RSS

过滤 eth0 中断号,绑定到 0-7 号 CPU 核上(eth0-fp 命名可能有所不同):

root@geekwolf:~# grep eth0-fp /proc/interrupts |awk '{print $1, $NF}'
147: eth0-fp-0
148: eth0-fp-1
149: eth0-fp-2
150: eth0-fp-3
151: eth0-fp-4
152: eth0-fp-5
153: eth0-fp-6
154: eth0-fp-7

echo 1  >/proc/irq/147/smp_affinity
echo 2  >/proc/irq/148/smp_affinity
echo 4  >/proc/irq/149/smp_affinity
echo 8  >/proc/irq/150/smp_affinity
echo 10 >/proc/irq/151/smp_affinity
echo 20 >/proc/irq/152/smp_affinity
echo 40 >/proc/irq/153/smp_affinity
echo 80 >/proc/irq/154/smp_affinity

可以通过 top 命令查看%si 是否均衡分摊到 0-7 核 CPU

注意事项

1、启动 irqbalance 后,手动绑定将失效

2、当 CPU 工作在最高性能模式时,irqbalance 会均匀分配中断到其他 CPU,节能模式时中断会集中分配到 CPU0

3、以上设置均以网卡支持多队列为前提,建议手动绑定 SMP IRQ affinity

网卡多队列需 tg3,bnx2,bnx2x,b44 等驱动的支持,Broadcom 的网卡驱动已经内置在内核中向后兼容大部分的 2.6 内核及大于 2.4.24 的 2.4 内核

4、笔者实际测试过程中遇到 BladeCenter HS23 刀片服务器 Emulex Corporation OneConnect 10Gb NIC (be3)本身支持多队列,在连接到千兆网 5、环境下无法使用多队列问题,万兆网络下可以使用,只好通过下面 RPS/RFS 方式实现

RPS/RFS

Receive Packet Steering/Receive Flow Streering,软件方式实现 CPU 均衡,接收包中断的优化

RPS: 网卡驱动对每一个数据库包根据四元组(SIP,SPORT,DIP,DPORT)生成 HASH 值,通过 HASH 值将每个连接和 CPU 绑定

RFS: 由于 RPS 只是单纯的把数据包均衡到不同的 CPU 上,此时如果应用程序所在 CPU 和中断处理的 CPU 不在同一个核,将会对 CPU Cache 影响很大,RFS 的作用就是将应用程序和软中断处理分配到同一个 CPU

配置步骤:

根据上述说明一个十六进制 f 表示四个 CPU 核,那么均衡到 32 核即 ffffffff

配置 RPS

rps_cpus='ffffffffff'
for rxdir in /sys/class/net/eth0/queues/rx-*
do
    echo $rps_cpus >$rxdir/rps_cpus
done

配置 RFS

RFS 扩展了 RPS 的性能以增加 CPU 缓存命中率,减少网络延迟,默认是禁用的

/proc/sys/net/core/rps_sock_flow_entries

设置此文件至同时活跃连接数的最大预期值。对于中等服务器负载,推荐值为 32768 。所有输入的值四舍五入至最接近的 2 的幂

/sys/class/net/device/queues/rx-queue/rps_flow_cnt

将 device 改为想要配置的网络设备名称(例如,eth0),将 rx-queue 改为想要配置的接收队列名称(例如,rx-0)。

将此文件的值设为 rps_sock_flow_entries 除以 N,其中 N 是设备中接收队列的数量。例如,如果 rps_flow_entries 设为 32768,并且有 16 个配置接收队列,那么 rps_flow_cnt 就应设为 2048。对于单一队列的设备,rps_flow_cnt 的值和 rps_sock_flow_entries 的值是一样的

ls /sys/class/net/eth0/queues/rx-*|grep queues|wc -l
8

rps_flow_cnt=32768/8=4096
echo 32768 >/proc/sys/net/core/rps_sock_flow_entries
for rxdir in /sys/class/net/eth0/queues/rx-*
do
    echo $rps_cpus >$rxdir/rps_cpus
    echo $rps_flow_cnt >$rxdir/rps_flow_cnt
done

echo 32768 >/proc/sys/net/core/rps_sock_flow_entries

优化脚本可参考: https://github.com/geekwolf/sa-scripts/blob/master/ops-scripts/performance_tuning/set_rps.sh

网卡常规优化方案

关于发包的优化 XPS 还未做测试,有时间在做补充!

参考

原文连接:http://www.simlinux.com/archives/1798.html


最后修改 September 3, 2024: 中断, perf (51dbc4de)