![为什么 ping 结果随 CPU 负载而变化](https://linux22.com/image/212482/%E4%B8%BA%E4%BB%80%E4%B9%88%20ping%20%E7%BB%93%E6%9E%9C%E9%9A%8F%20CPU%20%E8%B4%9F%E8%BD%BD%E8%80%8C%E5%8F%98%E5%8C%96.png)
我正在尝试在通过第 2 层交换机连接的两台运行 Ubuntu 20.04 的 PC 之间执行 ping 操作。我的目标是获得“几乎”稳定的 ping 延迟。与其他人类似,我发现低 CPU 负载下的 ping 延迟(往返时间)比高 CPU 负载下更糟糕。
https://superuser.com/questions/543503/ping-vs-cpu-usage
https://superuser.com/questions/1189531/kvm-how-is-cpu-usage-lated-to-ping
例如,假设我从 PC-A ping 到 PC-B。当 PC-B 未运行操作系统中默认程序以外的任何程序时,PC-A 上收到的 ping 延迟约为 0.5 - 0.6 毫秒。然而,当我使用压力工具增加 CPU 负载(例如,将一个核心压力提高到 80% 负载)时,我发现 PC-A 上收到的 ping 延迟仅为 0.2 - 0.3 毫秒左右。
我确信问题不是由交换机引起的,因为我也尝试过 PC-A 和 PC-B 之间的直接电缆,但仍然得到相同的行为。我非常确定这种行为是由省电模式引起的,这是默认的 CPU 指示器。但令我惊讶的是,当我使用以下命令将 CPU 指示器从省电模式更改为性能模式时cpu频率工具,PC-A 上收到的 ping 延迟仍约为 0.5 - 0.6 毫秒(PC-B 上无负载)。当我增加 CPU 负载时,也会发生相同的行为(ping 延迟约为 0.2 - 0.3 毫秒)。除了改变CPU指标之外,我想我还需要做点别的事情。
答案1
在低负载下,如果启用了节能以太网 (EEE),网络硬件将进入睡眠状态。这可能会导致延误。内核根据网络使用情况动态猜测何时小睡。
您可以通过以下方式禁用此功能按照这个答案。
答案2
例如,假设我从 PC-A ping 到 PC-B。当 PC-B 未运行操作系统中默认程序以外的任何程序时,PC-A 上收到的 ping 延迟约为 0.5 - 0.6 毫秒。
它可能测量接收和回复数据包的时间,以及 CPU 从空闲状态唤醒所需的时间(对我来说,这通常是 PLL 启动+锁定时间)并处理 IRQ。尝试使用 cpuidle.off=1 启动来进行测量。
我的目标是获得“几乎”稳定的 ping 延迟。
如果这是唯一的目标而不是 XY 问题,那么您可以使用以下一些内容来了解延迟的影响...
- 如上所述,通过使用 cpuidle.off=1 启动来禁用空闲。这样,我们就不必等待核心从任何浅睡眠模式中退出。
- 通过使用 isolcpus=$idOfCoreToIsolate 启动,在启动时隔离 cpu。完成后,默认情况下,隔离内核上将运行很少的内容(可能是定时器 IRQ)。这可能不是启动核心(通常是 0 或最后一个核心)。
- 通过查看 /proc/interrupts 来识别您的 NIC IRQ 号
- 如果使用 irqbalance:编辑 /etc/default/irqbalance 将隔离核心的相应位添加到 IRQBALANCE_BANNED_CPUS 并将 --banirq=$IRQNUM 添加到 IRQBALANCE_ARGS 并使用以下命令重新启动
sudo /etc/init.d/irqbalance restart
- 通过运行将 NIC IRQ 设置为隔离核心
echo $ISOLATEDCORENUM | sudo tee /proc/irq/$IRQNUM/smp_affinity_list
。或者,如果您的 NIC 有流量控制,则可能需要不同的配置。 - 禁用 RX 中断聚合延迟:
sudo ethtool -C <nicNameHere> rx-usecs 0
。这样,当收到 ICMP 数据包时,它将立即触发中断(如果我们有很多数据包并且不专门针对此任务优化系统,这将是低效的)。
这样,传入的 NIC 数据包接收 IRQ 将在 NIC 听到后立即运行,因为专用内核上没有中断聚合且很少有其他 IRQ 运行,并且隔离内核从不休眠。