第二部分 · 6 / 7

性能选项

rdmanet函数选项模式调优,把 Option 传给 Dial / Listen / ListenPacket。这一节过一遍每个选项的含义、默认值和何时该动它。

全部选项

Option作用默认
WithDevice("mlx5_3")按名字选网卡(CPU 网 vs GPU 网)第一块可用
WithPort(n)HCA 端口号(1 起)1
WithGIDIndex(n)GID 表索引(RoCE v2)0(示例常用 3)
WithQueueDepth(n)队列深度(同时在飞的 WR 数)128
WithBufferSize(n)每个 bounce buffer 槽大小(字节)64 KiB
WithHandshake()改用 TCP 带外握手关(用 rdma_cm)
WithPollMode(...)CQ 排空方式PollEvent
conn, _ := rdmanet.Dial(addr,
    rdmanet.WithDevice("mlx5_1"),
    rdmanet.WithGIDIndex(3),
    rdmanet.WithQueueDepth(256),
    rdmanet.WithPollMode(rdmanet.PollBusy),
)

轮询模式:延迟 vs CPU

这是最影响性能特征的旋钮,本质是一道权衡题:

模式做法特点
PollEvent默认等完成通道事件(ibv_get_cq_event),被唤醒后批量收割CPU 占用低,略有延迟。通用场景首选
PollBusy专用 goroutine 忙轮询 CQ延迟最低,吃满一个核。延迟敏感场景
为什么默认 PollEvent 事件驱动是对 CPU 友好的通用默认值;忙轮询是延迟敏感用户的显式选择。 PollEvent 是零值(iota 0),也是文档约定的默认。

队列深度与缓冲区大小

  • WithQueueDepth:允许同时在飞的工作请求数。调大能提升流水线深度、利好高带宽,但占用更多资源。
  • WithBufferSize:每个注册槽的大小。消息普遍偏大时调大可减少分片;偏小时调小省内存。

批量 I/O

每次 post/收割都有固定开销,批量 API 把若干消息在一把锁下一起处理,摊薄开销, 在小消息高频场景显著提升吞吐:

conn.SendBatch(msgs)        // 一次发多条
msgs, _ := conn.RecvBatch(32) // 一次最多收 32 条
// UD 侧对应 WriteToBatch / ReadFromBatch

零拷贝发送

默认 SendMsg 会把你的数据拷进库维护的 bounce buffer 再发。 如果你能从一块预注册的缓冲区直接构造数据,就能省掉这次拷贝:

buf, _ := conn.AllocBuffer(4096) // 调用方拥有的预注册 Buffer
// ……往 buf 里写数据……
conn.SendBuffer(buf)             // 直接从 buf 发,无 bounce 拷贝

UD 地址注册表

UD 无连接,发送前要知道对端 AddrRegistry 是个轻量的「名字→Addr」目录, 用来带外发现对端(也可以用任意手段分发 Addr.String()):

reg := rdmanet.NewRegistry()
pc.Register(reg, "node-a")     // 登记自己
addr, _ := reg.LookupAddr("node-b") // 查别人
下一步 最后一节讲一个工程上的巧思:跨平台 stub——为什么没有网卡也能编译和测试。
gordma 教程