Skip to content

同机零拷贝共享内存(SHM)

可用性:完整版(Full)专属;精简版(Tiny)头文件中相关声明被剔除,误用会在编译期报错——这是一条明确的能力边界,而非运行期失败。

概述

OnePath 的「同机自动 SHM」让同一台机器上的不同 OnePath 会话之间自动经共享内存 零拷贝传输数据,无需用户手动管理内存池。开启后,用户继续使用普通的发布 / 订阅 API; 会话打开时 OnePath 自动探测对端是否在本机——同机走共享内存,跨机自动回退普通网络传输, 整个过程对用户完全透明。

它解决的是同机大消息的零拷贝吞吐问题:消息不经过网络栈,省去内核态拷贝与协议封装 开销。需要强调的是,这是大消息吞吐优化,而非抗网络拥塞的低延迟手段。

快速上手

唯一入口是 onepath_config_enable_shm,在打开会话前的配置里调用一次:

c
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 中调大。

c
onepath_shm_opts_t opts = { .message_size_threshold = 0 };  /* 全零拷贝 */
onepath_config_enable_shm(cfg, &opts);

pool_size0 用引擎默认 16 MB;数据量极大时可调大。

如何确认 SHM 生效

onepath_topology_local() 观察邻居链路的 is_shm 字段:同机邻居为 1,跨机为 0。 参见 网络拓扑感知

c
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

OnePath™ 是西安汉为信息技术有限公司的注册商标。