FastDDS 零拷贝模式下多个 subscriber 的原理
FastDDS 新推出的零拷贝 (Zero Copy) 模式有很多难以理解的地方,在这里会持续做些整理。
目录
- 如何使用 ZeroCopy?
- ZeroCopy 理论上
subscriber和publisher会使用同一个内存地址,为什么打印出来的地址不同? - ZeroCopy 会分配多少空间,什么时候覆盖旧的样本?
qos.history().depth与qos.resource_limits().max_samples/extra_samples什么关系?
1. 如何使用 ZeroCopy?
满足以下条件才能使用 ZeroCopy [1]
- 不禁用 DataSharingQosPolicy。 使用 AUTO 可以自动启用零拷贝;
- 数据类型必须为
LoanableSequence; - 在 publisher 使用
loan_sample()write()discard_loan()操作数据样本; - 在 subscriber 使用
read()take()return_loan()访问数据样本,类似take_next_sample会执行一次拷贝。[2]
2. ZeroCopy 理论上 subscriber 和 publisher 会使用同一个内存地址,为什么打印出来的地址不同?
在程序里打印的是不同进程的虚拟地址,实际的物理地址是一样的,可以用 这个工具 查看。 [3]
1 | $ sudo ./src/v2p 57649 0x7fffed6671cc 0x4000 |
3. ZeroCopy 会分配多少空间,什么时候覆盖旧的样本?
创建 DataWriter 时,Fast DDS 将预先分配 max_samples + extra_samples 个样本池,这些样本位于共享内存映射文件中。当调用 loan_sample() 函数时,该池将用于借出样本。
如 此文档 所述,在写入 resource_limits().max_samples + resource_limits().extra_samples 次后,样本将被覆盖。
可以在 DataReader 上使用方法 is_sample_valid 来检查样本是否已被覆盖。
4. qos.history().depth 与 qos.resource_limits().max_samples/extra_samples 什么关系?
history() 的设置会覆盖 resource_limits(),具体的,ResourceLimitsQosPolicy::allocated_samples/max_samples 通过 HistoryQosPolicy::depth 和 ResourceLimitsQosPolicy::max_instances 重新计算,公式如下:
1 | max_samples = depth * allocated_samples |