我最开始做 DPDK 开发时在优化系统时都会重点关注cache missNUMAPCIequeue backlogfalse sharingmemory stall因为这些问题确实会严重影响性能。但我曾经遇到过一个更加诡异的问题系统平均性能很好PPS 很稳定CPU 也不高没有丢包没有 queue 积压然而业务 RTT却会偶发性瞬间暴涨几十毫秒。而且这种 spike不是几十微秒。而是20ms 50ms 甚至 100ms最奇怪的是发生时所有 worker core像“同时冻结”了一样。第一次遇到时我怀疑过网卡 resetPCIe errorNIC firmwareCPU thermal throttlingsoft lockup最后才发现真正的问题竟然是TLB shootdown。而这个问题也让我真正理解了现代 Linux 多核系统中“修改页表”可能比处理 packet 更昂贵。一、问题现场系统双路 Xeon32 worker corehugepage memoryDPDK userspace networking程序长期运行整体性能很好。但监控平台总会出现随机 latency spike二、真正奇怪的地方这些 spike非常短暂。例如正常 RTT40us突然 spike80ms随后恢复正常40us像“系统暂停”了一下。三、CPU 没有打满查看top -HCPU并没有100%。甚至只有60%四、没有 packet loss网卡无 error。descriptor正常。queue也没 backlog。五、第一次怀疑是不是 scheduler 抢占因为“瞬间冻结”很像Linux scheduler。于是做isolcpusnohz_fullrcu_nocbs结果问题仍然存在。六、后来终于看到关键日志偶然发现TLB shootdown相关 trace。这里第一次意识到问题可能与虚拟内存系统 有关。七、什么是 TLBCPU访问内存时需要virtual address - physical address转换。这个转换如果每次都查页表。会极慢。于是CPU 使用TLBTranslation Lookaside Buffer缓存地址映射。八、为什么 TLB 很重要因为TLB miss代价非常高。可能涉及page table walkmemory access多级页表查询现代 CPUTLB 性能极其关键。九、什么是 TLB shootdown问题来了。如果某个 CPU修改了页表。例如munmapmprotectmemory reclaimpage migration那么其他 CPUTLB 中的旧映射就失效了。十、于是 Linux 必须通知所有 CPU即“你们的 TLB 缓存过期了。”这个过程叫TLB shootdown。十一、为什么它会导致“全核卡死”因为Linux 会发送IPIInter-Processor Interrupt给其他 CPU。要求它们停下当前工作flush TLBacknowledge然后才能继续运行。十二、为什么 DPDK 特别怕这个问题因为DPDK通常busy polling高频 packet loop极低时延任何几十微秒级别的暂停都会被放大。更别说几十毫秒十三、真正的问题终于暴露后来终于发现系统里某个模块周期性执行munmap()释放大块 memory。于是Linux频繁global TLB invalidation。十四、为什么“一个线程”会影响所有 core因为TLB是per-core cache。修改页表后必须所有 core 同步。否则某些 core会继续使用错误映射。十五、为什么多核系统更严重例如4 coreshootdown 较快。64 core需要64 个 CPU全部响应。同步成本暴涨。十六、为什么 spike 会越来越严重随着core 数增加IPI trafficsynchronization latencycache disruption都会恶化。十七、perf 数据终于暴露真相后来使用perf sched以及trace-cmd看到大量TLB flush IPI事件。十八、为什么 hugepage 能缓解问题因为TLB entry数量有限。普通4KB page需要大量 TLB entry。而2MB hugepage1GB hugepage可以减少TLB pressure。十九、但 hugepage 不能完全解决因为shootdown 的核心问题不是TLB miss。而是页表修改同步。二十、真正修复方案后来做了几个关键优化。1. 禁止 runtime munmap所有大内存启动时预分配。2. 避免频繁 mprotect不再动态改权限。3. 使用固定 hugepage pool避免动态扩缩容。4. memory recycle对象回收到 pool。而不是释放给 OS。二十一、优化后效果优化前指标数值Avg RTT40usP99980ms优化后指标数值Avg RTT38usP99970us系统稳定性完全不同。二十二、为什么很多人从未意识到这个问题因为TLB shootdown不会报错不会 crash不会丢包CPU usage 也正常只是随机“全系统停顿”。二十三、进一步理解 Linux 虚拟内存现代 Linux最复杂的部分之一其实是memory management。尤其page tableTLB coherenceNUMA migrationpage reclaim这些。二十四、DPDK 为什么极度强调“预分配”现在你会发现DPDK 官方设计几乎都在避免runtime allocationdynamic mappingpage operation原因之一就是避免TLB disturbance。二十五、一个非常经典的误区很多人认为高性能网络优化主要是SIMDbatchlockless实际上系统级 jitter很多来自OS memory subsystem。二十六、工程经验总结做低时延 DPDK一定要避免munmap高频 mmap动态 hugepage 调整page migrationmemory reclaim否则TLB shootdown可能毁掉整个 tail latency。二十七、这次排查真正学到什么以前我以为虚拟内存只是“操作系统基础知识”。后来才意识到真正影响高性能系统稳定性的很多时候是TLB coherence。因为现代 CPU性能越高。越依赖缓存。而TLB 本质上也是一种 cache。二十八、总结为什么 DPDK 程序会偶尔“瞬间卡死”几十毫秒很多时候不是NIC 问题CPU 问题queue 问题而是TLB shootdown。通过这次问题我们真正理解了核心概念TLBpage tableTLB shootdownIPIvirtual memoryhugepage这也是高性能网络开发真正进入“操作系统底层机制优化”的开始真正影响 tail latency 的。可能已经不是 packet processing。而是页表同步。