第三部分 · 2 / 9

go_rdmanet_bw 详解

go_rdmanet_bw 不只是「高层带宽工具」——它内置了三种发送方式,正好对应 rdmanet 从易用到极致吞吐的不同档位。理解这三种模式,也就理解了高层 API 的性能边界在哪。

三种模式速查

模式开关用的 API典型吞吐(64KB)
逐条发送默认Conn.SendMsg~18 Gb/s
批量消息-b NConn.SendBatch~28 Gb/s
RawConn--rawRawConn.PipelineBatch~210 Gb/s

(吞吐为某台 400G RoCE v2 主机上的实测量级,仅供横向对比,会随硬件/配置变化。)

先对齐单位 横向比较前务必把单位换算到同一口径,否则会差出 8 倍。--raw 现在输出 MiB/s(2²⁰,与 ib_send_bw 同口径,可直接比);Go 版 go_send_bw 输出 MB/s(10⁶ byte/s,×8÷1000 得 Gb/s);C 版 ib_send_bw 输出 MiB/s (2²⁰ byte/s,×2²⁰×8÷10⁹ 得 Gb/s)。同机 64KB 多次实测峰值换算后约为:ib_send_bw ~392 Gb/s、go_send_bw ~392 Gb/s(可追平 C)RawConn ~232 Gb/s。 注意这台共享 GPU 机抖动很大(±25%),单次数字不可比,详见 CGO 开销与原生 RDMA 的差距

模式一:默认逐条 SendMsg

不带任何开关时,客户端逐条 SendMsg。这是延迟受限的——同一时刻只有一条消息 in-flight, 吞吐 ≈ 1/单条往返延迟,远喂不满网卡。它演示的是 Conn 最朴素的用法,不是性能档。

./bin/go_rdmanet_bw -d mlx5_1 -x 3                          # 服务端
./bin/go_rdmanet_bw -s 65536 -n 1000000 -d mlx5_1 -x 3 33.0.226.25:18515

模式二:--batch 批量消息

-b N(即 --batch)后,客户端改用 SendBatch、服务端用 RecvBatch, 摊薄每次调用的固定开销。注意:Conn 仍带封帧、信用流控、bounce 拷贝,所以即便批量, 吞吐提升也有限——这恰恰是 RawConn 存在的理由。

./bin/go_rdmanet_bw -d mlx5_1 -x 3 -b 32                    # 服务端(两端 -b 不必一致,但都要够大)
./bin/go_rdmanet_bw -s 65536 -n 1000000 -d mlx5_1 -x 3 -b 32 33.0.226.25:18515

输出带模式标签,例如 SendBatch(32): sent ... Gb/s, ... Mpps。 服务端无需 -n——收到客户端关闭(io.EOF)即结束。

模式三:--raw 极限吞吐

--raw 切到 RawConn:无封帧、无流控、单 goroutine post+busy-poll, 吞吐量级接近底层 perftest(峰值约为 go_send_bw 的 0.6 倍,但实测两者差距随机器状态在 1.05×~1.76× 间波动、某些轮次几乎持平;差距落在完成到达(poll)而非 cgo 提交,详见 CGO 开销与原生 RDMA 的差距,用 GORDMA_PROBE=1 可量化)。 此模式下 -b 的含义变为 tx-depth(in-flight WR 数)。

./bin/go_rdmanet_bw --raw -d mlx5_1 -x 3 -b 128             # 服务端
./bin/go_rdmanet_bw --raw -s 65536 -n 1000000 -d mlx5_1 -x 3 -b 128 33.0.226.25:18515

输出为 ib_send_bw 风格的表格(BW average[MiB/sec] + MsgRate[Mpps]),可与 ib_send_bw 直接并排比较。RawConn 恒用 TCP 握手 + 忙轮询,所以 --poll/--handshake 在此模式被忽略。

大包 vs 小包 64KB 大包很快撞到带宽线速(Gb/s 见顶);要看批量提交对消息率的收益,测小包更明显: --raw -s 1024 -n 5000000 -b 128 的 Mpps 会比大包高一个数量级。

对齐 perftest:诊断开关

想搞清「RawConn 为什么比 go_send_bw 慢」,把 RawConn 的跑法逐项对齐到 perftest 基线,再看差距落在哪:

开关作用
--raw-onebuf收发两端都复用单块固定区域(而非轮转 tx-depth 个槽位),对齐 perftest 的热工作集。两端都要加。
--raw-single客户端逐条 PostSendPipeline)而非批量提交(PipelineBatch),对齐 go_send_bw
GORDMA_PROBE=1环境变量,打开后客户端额外打印 post(提交 WR 耗时占比)vs poll(忙等完成耗时占比)。poll 占比高=瓶颈在网卡/对端;post 占比高=瓶颈在提交路径(cgo)。
# 完全对齐 go_send_bw,并打开探针看时间花在哪
GORDMA_PROBE=1 ./bin/go_rdmanet_bw --raw --raw-onebuf -d mlx5_1 -x 3 -b 128                              # 服务端
GORDMA_PROBE=1 ./bin/go_rdmanet_bw --raw --raw-onebuf --raw-single -s 65536 -n 1000000 -d mlx5_1 -x 3 -b 128 33.0.226.25:18515

其它实用开关

开关作用
--depth N队列深度 / 信用窗口(两端一致才有对照意义;0=库默认 128)
--poll busy|event非 raw 模式的 CQ 排空方式:忙轮询低延迟、事件驱动省 CPU
--handshake非 raw 模式改用 TCP 握手而非 rdma_cm

怎么选模式

  • 想看「最朴素的 Conn 能跑多少」→ 默认模式。
  • 想看「批量摊薄开销的效果」→ -b N
  • 想看「rdmanet 能逼近多少网卡线速」→ --raw,再配大 -b(tx-depth)。
  • 想要绝对基准 → 直接跑底层 go_send_bw 对照。
下一步 这些模式共享一套命令行参数。下一节是 通用命令行参数 速查。
gordma 教程