我有一个 Ubuntu VM,在基于 Ubuntu 的 Xen XCP 中运行。它托管一个基于 FCGI 的自定义 HTTP 服务nginx
。
负载下ab
第一个 CPU 核心已饱和,其余核心负载不足。
我/proc/interrupts
看到CPU0 提供的中断比任何其他核心都要多一个数量级。其中大多数来自eth1
。
我可以做些什么来提高此虚拟机的性能?有没有办法更均匀地平衡中断?
血腥细节:
$ uname -a Linux MYHOST 2.6.38-15-virtual #59-Ubuntu SMP 2012 年 4 月 27 日星期五 16:40:18 UTC i686 i686 i386 GNU/Linux $ lsb_release-a 无可用的 LSB 模块。 分销商 ID:Ubuntu 描述:Ubuntu 11.04 发行:11.04 代号:natty $ cat /proc/interrupts CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 283:113720624 0 0 0 0 0 0 0 xen-dyn-事件 eth1 284:1 0 0 0 0 0 0 0 xen-dyn-事件 eth0 285:2254 0 0 3873799 0 0 0 0 xen-dyn-事件 blkif 286:23 0 0 0 0 0 0 0 xen-dyn-事件 hvc_console 287:492 42 0 0 0 0 0 295324 xen-dyn-事件 xenbus 288:0 0 0 0 0 0 0 222294 xen-percpu-ipi callfuncsingle7 289:0 0 0 0 0 0 0 0 xen-percpu-virq debug7 290:0 0 0 0 0 0 0 151302 xen-percpu-ipi callfunc7 291:0 0 0 0 0 0 0 3236015 xen-percpu-ipi resched7 292:0 0 0 0 0 0 0 60064 xen-percpu-ipi spinlock7 293:0 0 0 0 0 0 0 12355510 xen-percpu-virq timer7 294:0 0 0 0 0 0 803174 0 xen-percpu-ipi callfuncsingle6 295:0 0 0 0 0 0 0 0 xen-percpu-virq 调试6 296:0 0 0 0 0 0 60027 0 xen-percpu-ipi callfunc6 297:0 0 0 0 0 0 5374762 0 xen-percpu-ipi resched6 298:0 0 0 0 0 0 64976 0 xen-percpu-ipi spinlock6 299:0 0 0 0 0 0 15294870 0 xen-percpu-virq timer6 300:0 0 0 0 0 264441 0 0 xen-percpu-ipi callfuncsingle5 301:0 0 0 0 0 0 0 0 xen-percpu-virq 调试5 302:0 0 0 0 0 79324 0 0 xen-percpu-ipi callfunc5 303:0 0 0 0 0 3468144 0 0 xen-percpu-ipi resched5 304:0 0 0 0 0 66269 0 0 xen-percpu-ipi spinlock5 305:0 0 0 0 0 12778464 0 0 xen-percpu-virq 计时器5 306:0 0 0 0 844591 0 0 0 xen-percpu-ipi callfuncsingle4 307:0 0 0 0 0 0 0 0 xen-percpu-virq 调试4 308:0 0 0 0 75293 0 0 0 xen-percpu-ipi callfunc4 309:0 0 0 0 3482146 0 0 0 xen-percpu-ipi resched4 310:0 0 0 0 79312 0 0 0 xen-percpu-ipi spinlock4 311:0 0 0 0 21642424 0 0 0 xen-percpu-virq 计时器4 312:0 0 0 449141 0 0 0 0 xen-percpu-ipi callfuncsingle3 313:0 0 0 0 0 0 0 0 xen-percpu-virq 调试3 314:0 0 0 95405 0 0 0 0 xen-percpu-ipi callfunc3 315:0 0 0 3802992 0 0 0 0 xen-percpu-ipi resched3 316:0 0 0 76607 0 0 0 0 xen-percpu-ipi spinlock3 317:0 0 0 16439729 0 0 0 0 xen-percpu-virq 计时器3 318:0 0 876383 0 0 0 0 0 xen-percpu-ipi callfuncsingle2 319:0 0 0 0 0 0 0 0 xen-percpu-virq 调试2 320:0 0 76416 0 0 0 0 0 xen-percpu-ipi callfunc2 321:0 0 3422476 0 0 0 0 0 xen-percpu-ipi resched2 322:0 0 69217 0 0 0 0 0 xen-percpu-ipi 自旋锁2 323:0 0 10247182 0 0 0 0 0 xen-percpu-virq 计时器2 324:0 393514 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle1 325:0 0 0 0 0 0 0 0 xen-percpu-virq 调试1 326:0 95773 0 0 0 0 0 0 xen-percpu-ipi callfunc1 327:0 3551629 0 0 0 0 0 0 xen-percpu-ipi resched1 328:0 77823 0 0 0 0 0 0 xen-percpu-ipi 自旋锁1 329:0 13784021 0 0 0 0 0 0 xen-percpu-virq 计时器1 330:730435 0 0 0 0 0 0 0 xen-percpu-ipi callfuncsingle0 331:0 0 0 0 0 0 0 0 xen-percpu-virq debug0 332:39649 0 0 0 0 0 0 0 xen-percpu-ipi callfunc0 333:3607120 0 0 0 0 0 0 0 xen-percpu-ipi resched0 334:348740 0 0 0 0 0 0 0 xen-percpu-ipi spinlock0 335:89912004 0 0 0 0 0 0 0 xen-percpu-virq timer0 NMI:0 0 0 0 0 0 0 0 不可屏蔽中断 LOC: 0 0 0 0 0 0 0 0 本地定时器中断 SPU:0 0 0 0 0 0 0 0 虚假中断 PMI:0 0 0 0 0 0 0 0 性能监控中断 IWI: 0 0 0 0 0 0 0 0 IRQ 工作中断 RES:3607120 3551629 3422476 3802992 3482146 3468144 5374762 3236015 重新安排中断 CAL: 770084 489287 952799 544546 919884 343765 863201 373596 函数调用中断 TLB:0 0 0 0 0 0 0 0 TLB 被击落 TRM: 0 0 0 0 0 0 0 0 热事件中断 THR:0 0 0 0 0 0 0 0 阈值 APIC 中断 MCE:0 0 0 0 0 0 0 0 机器检查异常 MCP:0 0 0 0 0 0 0 0 机器检查轮询 错误:0 错误信息:0
答案1
查看/proc/irq/283
目录。有一个smp_affinity_list
文件显示哪些 CPU 将获得 283 中断。对于您来说,此文件可能包含“0”(也smp_affinity
可能包含“1”)。
您可以将 CPU 范围写入文件smp_affinity_list
:
echo 0-7 | sudo tee /proc/irq/283/smp_affinity_list
或者您可以编写一个位掩码,其中每个位对应一个 CPU,以便smp_affinity
:
printf %x $((2**8-1)) | sudo tee /proc/irq/283/smp_affinity
然而,中断平衡众所周知,它对每个中断应具有的亲和性有自己的想法,并且可能会恢复您的更新。因此,最好完全卸载 irqbalance。或者至少停止它并禁止它在重新启动时出现。
如果即使没有 irqbalance,您在重启后仍遇到smp_affinity
中断 283 异常,那么您必须在其中一个启动脚本中手动更新 CPU 亲和性。
答案2
如果您拥有正确型号的英特尔 NIC,您可以显著提高性能。
引用第一段:
多核处理器和最新的以太网适配器(包括 82575、82576、82598 和 82599)允许通过将执行流分配给各个核心来优化 TCP 转发流。默认情况下,Linux 会自动将中断分配给处理器核心。目前有两种方法可以自动分配中断,即内核 IRQ 平衡器和用户空间中的 IRQ 平衡守护进程。这两种方法都提供了可能降低 CPU 使用率但不会最大化 IP 转发率的权衡。可以通过手动将以太网适配器的队列固定到特定处理器核心来获得最佳吞吐量。
对于 IP 转发,发送/接收队列对应使用相同的处理器核心,并减少不同核心之间的任何缓存同步。这可以通过将发送和接收中断分配给特定核心来实现。从 Linux 内核 2.6.27 开始,可以在 82575、82576、82598 和 82599 上使用多个队列。此外,在扩展消息传递信号中断 (MSI-X) 中启用了多个发送队列。MSI-X 支持更多可用的中断,从而允许更精细地控制并将中断定位到特定 CPU。
答案3
实际上建议,特别是在处理短时间内重复的过程时,由设备队列生成的所有中断都由同一个 CPU 处理,而不是 IRQ 平衡因此,如果单个 CPU 处理下面提供的 eth1 中断*** 异常,您将看到更好的性能
上面链接的来源来自 Linux 研讨会,我建议你阅读一下SMP IRQ 亲和性因为它比这篇文章更能有效地说服你。
为什么?
回想一下,每个处理器除了能够访问主内存外,还有自己的缓存,看看这个图表触发中断时,CPU 核心必须从主内存中获取处理中断的指令,这比指令在缓存中花费的时间要长得多。一旦处理器执行了一项任务,它就会将这些指令保存在缓存中。现在假设同一个 CPU 核心几乎一直处理同一个中断,中断处理程序函数不太可能离开 CPU 核心缓存,从而提高内核性能。
或者,当IRQ平衡时,它可以将中断不断地分配给不同的CPU来处理,那么新的CPU核心很可能在缓存中没有中断处理程序函数,并且需要很长时间才能从主内存中获取适当的处理程序。
例外:如果您很少使用 eth1 中断,这意味着经过足够的时间后缓存会被执行其他任务所覆盖,这意味着您会在较长的时间间隔内间歇性地通过该接口传输数据……那么您很可能不会看到这些好处,因为它们是在您以高频率使用某个进程时产生的。
结论
如果您的中断发生非常通常只需将该中断绑定到特定 CPU 即可。此配置位于
/proc/'IRQ number'/smp_affinity
或者
/proc/irq/'IRQ number'/smp_affinity
请参阅SMP IRQ 亲和性来自上面链接的来源的部分,它有说明。
或者
您可以通过增加 MTU 大小(巨型帧)来更改中断标志发出的频率(如果网络允许的话),或者更改为在收到大量数据包后而不是每个数据包时都发出标志,或者更改超时时间,以便在一定时间后发出中断。请谨慎使用时间选项,因为您的缓冲区大小可能在时间用完之前就已满。这可以使用ethtool这在链接源中有概述。
这个答案的长度已经接近人们不会阅读的长度,所以我就不赘述了,但根据你的情况,有很多解决方案...请查看来源:)