同机零拷贝共享内存(SHM)
可用性:完整版(Full)专属;精简版(Tiny)头文件中相关声明被剔除,误用会在编译期报错——这是一条明确的能力边界,而非运行期失败。
概述
OnePath 的「同机自动 SHM」让同一台机器上的不同 OnePath 会话之间自动经共享内存 零拷贝传输数据,无需用户手动管理内存池。开启后,用户继续使用普通的发布 / 订阅 API; 会话打开时 OnePath 自动探测对端是否在本机——同机走共享内存,跨机自动回退普通网络传输, 整个过程对用户完全透明。
它解决的是同机大消息的零拷贝吞吐问题:消息不经过网络栈,省去内核态拷贝与协议封装 开销。需要强调的是,这是大消息吞吐优化,而非抗网络拥塞的低延迟手段。
快速上手
唯一入口是 onepath_config_enable_shm,在打开会话前的配置里调用一次:
onepath_config_t cfg;
onepath_config_new(&cfg);
onepath_config_set_mode(cfg, "peer");
onepath_config_enable_shm(cfg, NULL); /* 全默认:阈值 3072 字节,池 16 MB */
onepath_open_with_config(&session, cfg);
onepath_config_destroy(cfg);
/* 之后照常用普通发布 / 订阅 —— 同机的另一个会话收到的就是零拷贝 SHM */
onepath_publisher_put(pub, data, len);订阅端无需任何特殊处理:onepath_subscribe 收到的样本与普通传输完全一致。
最佳实践:阈值调优
message_size_threshold 控制「多大的消息用 SHM 零拷贝缓冲」:
| 设定 | 行为 | 适用 |
|---|---|---|
| 默认 3072 字节 | 小于此走普通缓冲,大于此零拷贝 | 通用负载(推荐) |
0 | 所有消息都零拷贝 | 大消息为主、想省每条拷贝时 |
阈值只决定缓冲类型,不决定是否经网络栈
阈值只决定单条消息是否走零拷贝缓冲,不改变同机会话间是否经过网络栈(只要开了 SHM, 传输链路就不经过网络栈)。阈值对「小包延迟」的影响在实测中并不稳定——延迟的主导项是 消息调度而非缓冲类型,因此默认 3072 通常是安全选择,无需为小包特意调低。
全零拷贝模式的内存池压力
threshold=0(全零拷贝)模式下,所有消息都从共享内存池分配。大消息(接近池容量)高频 发送时可能因内存池压力导致分配失败——大消息高频场景仍建议用默认 3072。若需更大池, 可在 pool_size 中调大。
onepath_shm_opts_t opts = { .message_size_threshold = 0 }; /* 全零拷贝 */
onepath_config_enable_shm(cfg, &opts);pool_size 设 0 用引擎默认 16 MB;数据量极大时可调大。
如何确认 SHM 生效
用 onepath_topology_local() 观察邻居链路的 is_shm 字段:同机邻居为 1,跨机为 0。 参见 网络拓扑感知。
onepath_topo_local_t topo;
if (onepath_topology_local(session, &topo) == ONEPATH_OK) {
for (size_t i = 0; i < topo.num_neighbors; i++)
printf("neighbor %s: shm=%d\n",
topo.neighbors[i].sid, topo.neighbors[i].is_shm);
onepath_topology_local_free(&topo);
}跨机行为
共享内存只在本机内有效。跨机会话(不同物理机 / 虚拟机)之间,同机探测失败,OnePath 自动回退到普通网络传输,通信照常进行,is_shm 如实报告为 0。无需为跨机部署做任何 特殊处理——同一份开启 SHM 的代码在单机和跨机环境下都正确工作。
性能特征
「同机自动 SHM」的价值在于大消息的零拷贝吞吐:消息不经过网络栈,省去内核态拷贝与 协议封装开销。需要澄清一个常见误解:
「不经网络栈 ⇒ 一定抗压低延迟」并不成立
SHM 传输的用户态缓冲管理(分配 / 回收)对 CPU 与内存带宽压力较为敏感。在系统被打满 (CPU + 内存带宽双重压力)时,SHM 的往返延迟可能与普通网络传输一样劣化,小包场景甚至 更明显。SHM 的价值是大消息零拷贝吞吐,而非抗网络拥塞的低延迟。 对小包延迟,无需为了 「走 SHM」而刻意调低阈值。
限制与注意事项
- 共享内存只在本机内有效;跨机会话自动回退普通网络传输(见上节「跨机行为」)。
- 全零拷贝模式(
message_size_threshold=0)在大消息高频场景下可能因内存池压力分配失败, 大消息高频场景建议保留默认阈值,并在数据量极大时调大pool_size。 - 除「同机自动 SHM」外,OnePath 另提供一组手动 SHM 池 API(从内存池显式分配零拷贝 缓冲,对任意大小消息强制确定性零拷贝)。两者职责清晰、互不冲突、互不依赖——手动池 独立创建,不依赖
onepath_config_enable_shm;通常只需同机自动 SHM,手动池保留为 极致延迟 / 吞吐基准的高级通道。
API 参考
完整的函数签名、选项结构体与常量见 共享内存 API。