对一台线上虚拟查看软中断造成的CPU开销的时候,发现一个比较奇怪的现象,那就是所有的软中断几乎都是被一个CPU处理的。
先用top看si列,绝大部分都是消耗在CPU2上的,其它CPU只有很少。怎么样,你有没有和我一样感觉到一脸蒙圈呢?
Tasks: 1262 total, 5 running, 1257 sleeping, 0 stopped, 0 zombie
Cpu0 : 1.0%us, 1.7%sy, 0.0%ni, 93.4%id, 0.3%wa, 0.0%hi, 0.0%si, 3.6%st
Cpu1 : 99.3%us, 0.7%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 26.6%us, 12.5%sy, 0.0%ni, 38.4%id, 0.0%wa, 0.0%hi, 10.5%si, 12.1%st
Cpu3 : 19.8%us, 10.5%sy, 0.0%ni, 59.1%id, 0.0%wa, 0.0%hi, 0.6%si, 9.9%st
Cpu4 : 4.8%us, 4.5%sy, 0.0%ni, 62.9%id, 20.8%wa, 0.0%hi, 0.3%si, 6.7%st
Cpu5 : 4.6%us, 4.6%sy, 0.0%ni, 86.3%id, 0.0%wa, 0.0%hi, 0.0%si, 4.6%st
Cpu6 : 2.6%us, 2.6%sy, 0.0%ni, 74.7%id, 14.9%wa, 0.0%hi, 0.0%si, 5.2%st
Cpu7 : 2.3%us, 6.2%sy, 0.0%ni, 38.4%id, 48.2%wa, 0.0%hi, 0.3%si, 4.6%st
网卡和内核交互是通过软中断的方式来进行的。既然是中断,那就每个可中断到CPU的设备就都会有一个中断号。来,我们现在虚机上找到软中断对应的中断号。
# cat /proc/interrupts
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
.....
29: 1556 0 0 48 0 0 0 1936452763 PCI-MSI-edge virtio1-input.0
30: 1 0 0 0 0 0 0 0 PCI-MSI-edge virtio1-output.0
31: 0 0 0 0 0 0 0 0 PCI-MSI-edge virtio2-config
32: 4916 0 1938561333 0 0 0 31645 0 PCI-MSI-edge virtio2-input.0
33: 1551068 0 0 0 0 0 0 0 PCI-MSI-edge virtio2-output.0
其中的virtio1-output.0和virtio1-output.0对应的是虚拟网卡eth0的发送和接收队列。其中断号分别是29和30。virtio2-input.0和virtio2-output.0对应是eth1的发送和接收队列,其中断号分别是32和33。
我们分别查看着几个中断号的cpu亲和性配置:
# cat /proc/irq/29/smp_affinity
80
# cat /proc/irq/30/smp_affinity
08
# cat /proc/irq/32/smp_affinity
04
# cat /proc/irq/33/smp_affinity
01
原来虚拟机是通过将不同网卡的不同队列绑定在不同的CPU上来实现软中断均衡的。不过我们eth1是直接配在接入层的,它的读队列请求特别的多,因此32号“引脚”上的中断也会特别的多。自然和32亲和的04号CPU,也就是CPU2就会出现明显比其它CPU高的软中断了。
这下你明白了吧?
个人公众号“开发内功管理”,打通理论与实践的任督二脉。
扩展1:在实机上,原理是一样的。不过现在的实机上网卡都是多队列,也就是说eth0可能会有多个读取队列,多个写队列,都可以各自分开配其CPU亲和性。你手头如果有实机的话,可以试一试。
扩展2:当然了,这些值是可以修改的!如果有必要,你可以通过修改这些参数来达到将软中断散布在多个CPU上的目的。