4. 延迟测量工具

RDMA 网络性能调优的第一步,是建立一套可重复、可对比、可定位的延迟测量方法。perftest 套件(由 Mellanox/NVIDIA 维护)是业界最通用的 RDMA 基准测试工具集,其中 ib_write_bw、ib_read_lat、ib_send_lat 等命令分别覆盖了不同操作类型下的带宽与延迟特征。本章聚焦于“如何正确测量延迟”,并解释测量结果背后的协议语义。

4.1 核心原理:延迟测量为什么不能只看 ping

传统 ping 基于 ICMP 协议,经过内核网络协议栈,测量的是“主机到主机”的软件路径延迟,与 RDMA 数据路径无关。RDMA 延迟由以下四段组成:

  • 应用发起开销:用户态调用 ibv_post_send() 到硬件 WQE(Work Queue Element)被取走的耗时;
  • 硬件传输时延:网卡序列化、线缆传播、交换机转发(若跨节点);
  • 对端处理时延:接收端网卡 DMA 写入内存、完成通知(CQE)生成;
  • 应用轮询/唤醒开销:对端应用从 ibv_poll_cq() 获取完成并回写数据。

perftest 通过预建立队列对(QP)并固定内存,剔除了建链、页错误等一次性开销,测量的是稳定状态下的硬件+驱动+应用轮询延迟。其核心测量逻辑如下:

发送端:
  t1 = rdtsc() 或 clock_gettime()
  ibv_post_send(发送 64B 数据)
  等待 CQE
  t2 = rdtsc()
  单次延迟 = t2 - t1(包含对端回包时间)

接收端:
  收到数据后立即 post_send 回写(echo)

因此,ib_read_lat 测得的数值是往返时间(RTT)的一半,而非单向延迟。理解这一点对解读数据至关重要。

关键概念:perftest 默认使用 ibv_wc_TIMER 或 CPU 时间戳,测量精度受 CPU 频率调整影响。建议在 BIOS 中关闭 CPU 节能(C-states、P-states),或使用 --use_cpu_tsc 参数强制使用 TSC 寄存器。

4.2 工具矩阵与参数选择

perftest 套件中与延迟直接相关的工具有三个,各自模拟不同的 RDMA 语义:

工具 操作类型 典型延迟(同机/跨机) 适用场景
ib_send_lat SEND / RECV(双边操作) 0.8–1.5 µs 验证驱动栈、QP 建立、CQE 路径
ib_read_lat RDMA READ(单边操作) 0.6–1.2 µs 衡量内存读取延迟,常用于存储场景
ib_write_lat RDMA WRITE(单边操作) 0.5–1.0 µs 衡量纯数据写入,无需对端 CPU 参与

实际生产环境中,ib_write_bw 虽然名义上是带宽工具,但其 --latency 参数可以同时统计延迟分布,适合在打满带宽时观察延迟是否劣化。常用参数组合如下:

# 服务端(目标机)
ib_read_lat -d mlx5_0 -i 1 -s 64 -t 100 -F

# 客户端(发起机)
ib_read_lat -d mlx5_0 -i 1 -s 64 -t 100 -F 192.168.1.10

# 参数说明:
# -d  指定 RDMA 设备(如 mlx5_0)
# -i  指定端口号(通常为 1)
# -s  消息大小(字节),延迟测试常用 64B
# -t  测试时长(秒)
# -F  强制使用 RoCEv2 模式(若为 InfiniBand 则不需要)
# --report_gbits  以 Gbit/s 显示带宽(配合 bw 工具)
常见陷阱:若两端 -d 指定的设备不一致,或未使用 --rdma_cm 指定连接模式,工具可能回退到 TCP socket 模拟路径,测出的延迟会虚高 10–20 倍。务必在两端执行 ibv_devinfo 确认设备状态为 PORT_ACTIVE。

4.3 方法流程:从环境检查到数据解读

一次可靠的延迟测量应遵循以下流程,每一步都可能成为延迟异常的来源:

  1. 物理层检查:确认链路速率(ibstat 查看 Rate: 100 表示 100Gb/s)、信号完整性(LinkUp 且无 CRC 错误)。
  2. 驱动与固件核对:两端 ethtool -i mlx5_0 查看驱动版本,mlxup 查询固件是否一致。版本不匹配会导致协商降速。
  3. CPU 亲和性绑定:使用 taskset -c 2 将测试进程绑定到与网卡同 NUMA 节点的 CPU 核心,避免跨 NUMA 访问增加 200–400 ns 延迟。
  4. 执行测量:先跑 ib_read_lat -s 64 获取基础延迟,再跑 ib_write_bw --latency -s 64 观察并发压力下的延迟变化。
  5. 记录与对比:保存每次测试的 min/avg/max 和百分位数据(--p99 参数),建立基线库。

以下是一次典型输出的关键字段解读:

# ib_read_lat 输出示例
                    RDMA_Read Latency Test
 Dual-port       : OFF          Device         : mlx5_0
 Number of qps   : 1            Transport type : IB
 Connection type : RC           Using SRQ      : OFF
 发送大小        : 64 bytes
 测试时长        : 100 秒
 结果:
   Minimum latency : 0.52 µs
   Average latency : 0.58 µs
   Maximum latency : 3.21 µs
   P99 latency     : 0.79 µs

若 Average 与 Minimum 差距超过 0.3 µs,说明存在周期性抖动,需进一步排查中断合并(interrupt coalescing)或对端 CPU 负载。

4.4 案例:跨交换机延迟异常定位

场景描述:某分布式存储集群报告跨节点 RDMA 写延迟从 0.9 µs 恶化至 1.8 µs,但同机测试正常。

排查过程:

  • 第一步:两端分别执行 ib_read_lat -s 64,确认本机回环延迟 0.55 µs 正常,排除网卡故障;
  • 第二步:检查交换机端口 show interface counters,发现接收端端口存在 CRC_Errors 持续增长,判断为光模块信号劣化;
  • 第三步:更换光模块后延迟恢复至 0.95 µs,同时 ibstat 中 LinkDownedCounter 停止增长。

该案例说明,延迟测量不仅是软件测试,更是物理层健康度的敏感探针。建议在变更网络配置(如调整 MTU、启用 PFC)后,立即执行一轮 perftest 对比。

4.5 误区与复盘:延迟测试中的“隐形变量”

误区一:忽略消息大小的影响。 64B 与 4KB 消息的延迟差异可达 0.3–0.5 µs,因为大消息需要额外的 DMA 描述符和分片处理。生产环境应使用实际业务的消息大小进行测试。
误区二:将双向测试与单向测试混淆。 ib_read_bw 默认执行双向流量,其延迟统计包含了对端 CPU 处理回包的竞争。若需测量纯单向延迟,应使用 --bidirectional 参数显式控制。
误区三:忽视 CPU 频率缩放。 当 CPU 进入节能状态时,TSC 频率变化会导致时间戳偏差。使用 --use_cpu_tsc 前应确认 cpupower frequency-info 显示 driver: intel_pstate 且处于 performance 模式。

复盘建议:每次测试前记录以下环境快照,便于后续对比:

# 记录脚本片段
echo "=== CPU 频率 ===" && cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
echo "=== 网卡状态 ===" && ibstat | grep -E "State|Rate|Physical"
echo "=== 中断配置 ===" && cat /proc/irq/*/smp_affinity | head -5
echo "=== 固件版本 ===" && ethtool -i mlx5_0 | grep firmware

最后需要强调的是,perftest 测量的是理想条件下的硬件极限延迟,实际业务延迟通常比测试值高 20%–50%,因为应用层还有序列化、内存拷贝、锁竞争等开销。因此,建议将 perftest 结果作为“硬件基线”,再结合 ibv_async_watch 或内核 tracepoint 定位软件栈中的额外延迟。只有将工具测量与业务特征结合,才能准确判断延迟瓶颈究竟在网卡、交换机、驱动还是应用层。