转自 https://blog.youkuaiyun.com/yue530tomtom/article/details/76095739
参考https://blog.youkuaiyun.com/mrbuffoon/article/details/82839096 网卡多队列
https://www.cnblogs.com/flyfish919/p/7338418.html 网卡多队列
https://www.cnblogs.com/Bozh/archive/2013/03/21/2973769.html SMP IRQ affinity
其中最后一篇文档使用netperf对SMP IRQ affinity情况下的TCP小包、TCP大包、UDP小包、UDP打包进行了性能对比测试,有一定参考意义。
名词解释
IRQ: Interrupt ReQuest中断请求,IRQ号决定了需要被CPU处理的优先级。IRQ号越小意味着优先级越高。
SMP:(Symmetric Multi-Processing)对称多处理结构的简称,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构。可以理解为系统存在多个完全相同的CPU ,所有CPU共享总线,拥有自己的寄存器。对于内存和外部设备访问,由于共享总线,所以是共享的。 Linux 操作系统多个 CPU 共享在系统空间上映射相同,是完全对等的。
中断:是由硬件或软件发送的一种称为IRQ的信号,是一种CPU与硬件沟通的方式(还有另外一种叫轮询)。中断是一种电信号,由硬件产生,并直接送到中断控制器上,然后再由中断控制器向CPU发送信号,CPU检测到该信号后,就中断当前的工作转而去处理中断。然后,处理器会通知操作系统已经产生中断,这样操作系统就会对这个中断进行适当的处理。中断分为两个过程,中间以中断控制器作为分隔。上半部分即中断上半部,下半部分为中断下半部。上半部分大部分为所说的硬件中断,下半部分为软中断。
SMP IRQ affinity
APIC表示高级可编程中断控制器(Advanced Programmable Interrupt Controlle),APIC是SMP体系的核心,通过APIC可以将中断分发到不同的CPU来处理.即将中断绑定CPU或者把中断处理平摊到CPU上,这个过程叫做 SMP IRQ Affinity。
SMP IRQ affinity使用前提
1. 需要多CPU的系统,使用uname -a可以查询是否支持SMP
2. 需要大于等于2.4的Linux 内核 ,使用uname -r可以查询内核版本
3. 相关设置文件,设置/proc/irq/{IRQ}/smp_affinity和/proc/irq/{IRQ}/smp_affinity_list指定了哪些CPU能够关联到一个给定的IRQ源. 这两个文件包含了这些指定cpu的cpu位掩码(smp_affinity)和cpu列表(smp_affinity_list)。
绑定硬件中断到CPU
手动绑定 IRQ 到不同 CPU,需要先停掉 IRQ 自动调节的服务进程,否则自己手动绑定做的更改将会被自动调节进程给覆盖掉。
SMP_AFFINITY文件:在/proc/irq/{IRQ}/目录下都有一个smp_affinity文件,这个文件中,所表示的CPU核心以十六进制来表示的。
1、查找硬件IRQ号
[root@admin ~]# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
0: 27541 0 0 0 0 0 0 0 IO-APIC-edge timer
1: 9 0 0 0 0 0 0 0 IO-APIC-edge i8042
8: 1 0 0 0 0 0 0 0 IO-APIC-edge rtc0
9: 0 0 0 0 0 0 0 0 IO-APIC-fasteoi acpi
12: 109 0 0 0 0 0 0 0 IO-APIC-edge i8042
14: 0 0 0 0 0 0 0 0 IO-APIC-edge ata_piix
15: 57502472 0 0 0 0 0 0 0 IO-APIC-edge ata_piix
16: 69 0 0 0 0 0 1039981547 0 IO-APIC-fasteoi eth1
17: 0 0 0 0 0 0 0 0 IO-APIC-fasteoi ehci_hcd:usb1
19: 67 0 0 0 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb2
24: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
25: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
26: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
27: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
28: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
29: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
30: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
31: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
32: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
33: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
34: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
35: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
36: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
37: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
38: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
39: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
40: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
41: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
42: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
43: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
44: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
45: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
46: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
47: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
48: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
49: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
50: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
51: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
52: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
53: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
54: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
55: 0 0 0 0 0 0 0 0 PCI-MSI-edge pciehp
56: 4514 0 0 0 0 0 0 10837328 PCI-MSI-edge vmw_pvscsi
66: 1051805 0 0 0 0 0 0 0 PCI-MSI-edge vmci
67: 0 0 0 0 0 0 0 0 PCI-MSI-edge vmci
NMI: 0 0 0 0 0 0 0 0 Non-maskable interrupts
LOC: 1869449523 197290359 333847185 195402404 1716706473 156640980 3003939114 1708931297 Local timer interrupts
SPU: 0 0 0 0 0 0 0 0 Spurious interrupts
PMI: 0 0 0 0 0 0 0 0 Performance monitoring interrupts
IWI: 0 0 0 0 0 0 0 0 IRQ work interrupts
RES: 3394823095 1382776074 1674379986 943540239 374079686 184005614 115961174 91412940 Rescheduling interrupts
CAL: 2223 2424 3990 3988 3990 3979 3977 3484 Function call interrupts
TLB: 187257 546075 524015 282946 303969 157363 650465 740107 TLB shootdowns
TRM: 0 0 0 0 0 0 0 0 Thermal event interrupts
THR: 0 0 0 0 0 0 0 0 Threshold APIC interrupts
MCE: 0 0 0 0 0 0 0 0 Machine check exceptions
MCP: 27383 27383 27383 27383 27383 27383 27383 27383 Machine check polls
ERR: 0
MIS: 0
2、修改/proc/irq/{IRQ}/smp_affinity
注意smp_affinity这个值是一个十六进制的bitmask,它和cpu No.序列的“与”运算结果就是将affinity设置在那个(那些)CPU了。(也即smp_affinity中被设置为1的位为CPU No.)
如:8个逻辑core,那么CPU#的序列为11111111 (从右到左依次为CPU0~CPU7)
[root@admin ~]# cat /proc/irq/16/smp_affinity
00000000,00000000,00000000,00000040
/proc/irq/16/smp_affinity中的数字是16进制的,“40”转为二进制则为0100 0000, 这说明16号IRQ的亲和性为#6号CPU。
另外,cat /proc/irq/16/smp_affinity_list可以直接得到16号IRQ的亲和性CPU的十进制数字。
[root@admin ~]# cat /proc/irq/16/smp_affinity_list
6
如果你想设置16号IRQ绑定到多颗CPU,则可以修改 /proc/irq/16/smp_affinity。例如绑定16号IRQ到#5和#6CPU,如下:
[root@admin ~]# echo "00000000,00000000,00000000,00000060" > /proc/irq/16/smp_affinity
[root@admin ~]# cat /proc/irq/16/smp_affinity
00000000,00000000,00000000,00000060
[root@admin ~]# cat /proc/irq/16/smp_affinity_list
5-6
3. 停止irqbalance服务
需要先停掉 IRQ 自动调节的服务进程,否则自己手动绑定做的更改将会被自动调节进程给覆盖掉。
[root@admin ~]# service irqbalance status
irqbalance (pid 2569) is running...
[root@admin ~]# service irqbalance stop
Stopping irqbalance: [ OK ]
[root@admin ~]# service irqbalance status
irqbalance (pid 745) is running...
[root@admin ~]# service irqbalance stop
Stopping irqbalance: [ OK ]
[root@admin ~]# service irqbalance status
irqbalance is stopped
网卡负载均衡
SMP IRQ affinity主要针对多队列网卡多CPU环境。如何确定网卡是否支持多队列?
[root@localhost ~]# ethtool -l eth0
Channel parameters for eth0:
Pre-set maximums:
RX: 0
TX: 0
Other: 0
Combined: 2 # 这一行表示最多支持设置2个队列
Current hardware settings:
RX: 0
TX: 0
Other: 0
Combined: 1 #表示当前生效的是1个队列
[root@localhost ~]# ethtool -L eth0 combined 2 # 设置eth0当前使用2个队列
要确保多队列确实生效,可以查看文件:
# ls /sys/class/net/eth0/queues/
rx-0 rx-2 rx-4 rx-6 tx-0 tx-2 tx-4 tx-6
rx-1 rx-3 rx-5 rx-7 tx-1 tx-3 tx-5 tx-7
如上,如果rx数量是设定值,则正确。
使用总结
1、通过手动改变smp_affinity文件中的值来将IRQ绑定到指定的CPU核心上,或者启用irqbalance服务来自动绑定IRQ到CPU核心上。没有启动irqbalance 也没有合理的做手动 irq 绑定的话会有性能问题。手动 irq 只推荐给很 heavy、很特殊的情况,比如带多网卡多硬盘的网络存储服务器,一般机器一般应用还是用irqbalance 省心
2、在一个大量小包的系统上,irqbalance优化几乎没有效果,而且还使得cpu消耗分配的不均衡,导致机器性能得不到充分的利用,这个时候需要把它给结束掉。
3、对于文件服务器、高流量 Web 服务器这样的应用来说,把不同的网卡 IRQ 均衡绑定到不同的 CPU 上将会减轻某个 CPU 的负担,提高多个 CPU 整体处理中断的能力;
4、对于数据库服务器这样的应用来说,把磁盘控制器绑到一个 CPU、把网卡绑定到另一个 CPU 将会提高数据库的响应时间、优化性能。合理的根据自己的生产环境和应用的特点来平衡 IRQ 中断有助于提高系统的整体吞吐能力和性能。
5、DB可以设置一部分CPU处理硬盘IO,一部分CPU处理网络IO,多网卡服务器可以设置对应CPU对应网卡。当然具体情况看生产情况而定。