最近在做RDMA网络压测的时候,遇到了一个特别头疼的问题:不管是发小包还是大包,网卡利用率就是上不去,明明是100Gbps的网卡,实际跑出来的速率连一半都不到。相信很多搞高性能网络的兄弟都遇到过类似的问题,今天就来聊聊这里面的门道。
先说结论:RDMA不是万能药
很多人对RDMA有个误解,觉得它就是个"加速器",装上就能让网络性能飞起来。实际上,RDMA虽然绕过了内核协议栈,但它有自己的一套游戏规则,不按规则来,性能反而可能比传统TCP还差。
小包性能瓶颈:不是带宽,是延迟
CPU缓存失效是罪魁祸首
小包压测跑不满速,第一个要检查的就是CPU缓存命中率。RDMA虽然是零拷贝,但是每个包的处理还是需要CPU参与的。当包很小的时候,CPU处理每个包的开销相对就显得很大。
我之前做过一个实验,用64字节的包做压测,发现CPU L3缓存命中率只有60%多,这就很要命了。每次缓存失效,CPU就要去内存取数据,这一来一回就是几百个时钟周期。
# 用perf看看缓存命中率
perf stat -e cache-references,cache-misses ./your_rdma_test
中断绑定不合理
很多时候网卡中断没有绑定到合适的CPU核心上。RDMA网卡的中断处理是个重活,如果中断处理和应用程序跑在同一个核心上,或者跨NUMA节点了,性能就会大打折扣。
# 查看中断绑定情况
cat /proc/interrupts | grep mlx
# 绑定中断到指定CPU
echo 2 > /proc/irq/24/smp_affinity
队列深度设置不当
这个经常被忽略。小包的时候,如果Send Queue深度设置太小,网卡就会经常空转等待新的工作请求。但设置太大又会增加内存开销和延迟。
一般来说,小包压测建议SQ深度设置在512-2048之间,具体数值要根据你的应用特点来调。
大包性能瓶颈:带宽是表象,本质是内存
内存带宽才是真正的限制
100Gbps听起来很快,但换算成内存带宽就是12.5GB/s。现在的服务器内存带宽虽然标称能到几十GB/s,但那是理论峰值,实际可用的带宽要打个折扣。
特别是当你的RDMA应用和其他程序共享内存总线的时候,可用带宽就更有限了。我见过有些场景下,实际可用的内存带宽只有理论值的40-50%。
NUMA亲和性问题
这个问题特别隐蔽。如果你的应用程序在NUMA节点0上跑,但是网卡插在连接到NUMA节点1的PCIe插槽上,那数据就要跨NUMA节点传输,性能直接腰斩。
# 查看网卡在哪个NUMA节点
cat /sys/class/net/eth0/device/numa_node
# 查看进程的NUMA亲和性
numactl --show
PCIe带宽不够用
这个更容易被忽略。很多人以为PCIe 3.0 x16就够用了,实际上PCIe 3.0 x16的理论带宽是128Gbps,看起来比100Gbps网卡要高。但是PCIe是双向的,而且还有协议开销,实际可用带宽可能只有90-100Gbps。
如果你的服务器上还插了其他高带宽设备(比如NVMe SSD、GPU),PCIe带宽就更紧张了。
深层次原因分析
RDMA传输模式选择不当
RDMA有几种不同的传输模式:RC(Reliable Connection)、UC(Unreliable Connection)、UD(Unreliable Datagram)。不同模式的性能特点差别很大。
很多人默认用RC模式,但RC模式的连接管理开销比较大,小包场景下反而不如UD模式。
内存预分配策略有问题
RDMA需要把内存提前注册给网卡,这些内存不能被操作系统换出。如果内存分配策略不合理,就会导致内存碎片或者频繁的内存注册/注销操作。
我见过有些应用每次发包都重新分配内存,这样每次都要做内存注册,开销巨大。正确的做法是提前分配一个大的内存池,然后复用。
网卡驱动参数没调优
网卡驱动有很多参数可以调,但大多数人都用默认值。默认值通常是为了兼容性设计的,不一定是性能最优的。
# 查看网卡驱动参数
ethtool -g eth0
# 调整ring buffer大小
ethtool -G eth0 rx 4096 tx 4096
实战调优建议
小包优化策略
- CPU亲和性绑定:把应用程序绑定到网卡同一个NUMA节点的CPU上,避免跨节点访问。
- 中断负载均衡:如果有多个队列,把中断分散到不同的CPU核心上,避免单核瓶颈。
- 内存预热:压测前先把内存"摸"一遍,让相关的页面都加载到内存里。
- 批量处理:不要一个包一个包地发,尽量批量提交工作请求,减少系统调用开销。
大包优化策略
- 内存对齐:确保数据缓冲区按照CPU缓存行对齐,避免false sharing。
- 预取优化:在代码里加入适当的预取指令,让CPU提前加载数据到缓存。
- 零拷贝:尽量避免不必要的内存拷贝,直接在网卡注册的内存上操作。
- 并行化:如果可能的话,用多个队列并行传输,充分利用网卡的多队列能力。
系统级优化
监控和诊断工具
必备的性能监控命令
# 实时监控网卡统计
watch -n 1 'cat /proc/net/dev'
# 查看RDMA设备状态
ibstat
# 监控CPU使用情况
htop -d 1
# 查看内存使用
numastat -n
# 网卡性能计数器
ethtool -S eth0
性能分析工具链
- perf:分析CPU性能瓶颈,特别是缓存命中率
- iperf3:基础网络性能测试
- perftest:RDMA专用性能测试工具
- Intel VTune:深度性能分析(如果用Intel CPU的话)
常见误区和坑点
误区1:以为RDMA就是快
RDMA的优势是低延迟和CPU卸载,不是绝对的高带宽。如果你的应用本身就是CPU密集型的,RDMA可能帮不了太多忙。
误区2:忽略了内存子系统
很多人把注意力都放在网卡上,忽略了内存子系统的重要性。实际上,在高速网络环境下,内存往往是更容易成为瓶颈的地方。
误区3:网卡越贵性能越好
网卡性能不只看带宽,还要看PPS(每秒包数)能力。有些便宜的网卡在小包场景下反而比贵的网卡表现更好。
结语
RDMA网络压测跑不满速,原因通常不是单一的,而是多个因素叠加的结果。要想彻底解决问题,需要从CPU、内存、PCIe、网卡驱动等多个维度去分析和优化。
最重要的是,不要盲目相信理论数值,一定要结合实际的工作负载来调优。每个应用的特点不一样,最优的配置也不一样。
记住一点:做性能优化,测量比猜测重要。先搞清楚瓶颈在哪里,再有针对性地去解决,这样才能事半功倍。