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 |