恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
DDS中间件性能评测:RTI Connext、FastDDS、CycloneDDS吞吐延迟对比
首页
资讯中心
/
DDS中间件性能评测:RTI Connext、FastDDS、CycloneDDS吞吐延迟对比
DDS中间件性能评测:RTI Connext、FastDDS、CycloneDDS吞吐延迟对比
发布时间:2026/9/28 15:47:43
做机器人、自动驾驶或者工业控制系统的人迟早都会遇到DDS选型这个坎。尤其是当项目里有ROS2背景、或者需要从零搭一套分布式通信架构时RTI Connext、FastDDS、CycloneDDS这三款协议栈几乎是被反复拿来对比的对象。虽然它们都遵守OMG的DDS标准底层都跑RTPS协议但实测下来的吞吐、延迟、CPU占用、抖动表现差距比很多人想象中要大得多。这篇文章就把我自己搭建的一套评测方案、测出来的关键数据、以及排查过程中踩过的坑完整梳理一遍给准备做中间件选型或者正在调性能的朋友一个参考。1. 把DDS性能评测拆开看指标到底该测什么1.1 为什么同一套标准实现出来的性能千差万别很多刚接触DDS的人容易产生一个误解既然都符合DDSI-RTPS规范那三款协议栈的性能应该差不多。实际根本不是这么回事。DDS标准定义的是“接口行为、数据模型、发现机制、QoS策略”这些逻辑层面的东西至于底层怎么用UDP、怎么管理内存、怎么调度收发线程、怎么处理大数据包分段重组完全是各实现自己说了算。这就像同一个菜谱不同厨师用不同厨具、不同火候做出来的菜卖相和口感可以天差地别。DDS正常运行时的链路大致是通过SPDPSEDP做端点发现确认发布者和订阅者的对应关系然后通过可靠的UDP通道或者共享内存传输数据。每一步都有可优化的空间比如发现报文收发的频率、发送队列预分配策略、是否支持零拷贝、共享内存的申请与释放时机、线程在收到包以后是立即唤醒还是批量处理等等。这些细节累积起来就是最终性能和稳定性的差距所在。所以做评测本质上是在对比这些隐藏的设计取舍。1.2 性能评测的核心指标与测试前的一个概念澄清评测DDS性能不能只看一个“快”字。我一般固定看四类指标吞吐量单位时间内成功送达的字节数或者消息条数分别测量小包、中包、大包下的表现。延迟从发布者调用write到订阅者回调收到的端到端时间重点关注p50、p99、p999实时系统最大的敌人是尾延迟而不是平均延迟。抖动连续多次延迟的波动程度直接反映协议栈和操作系统调度的稳定性。资源占用稳态下的CPU占用率和RSS内存对于部署在嵌入式设备或者车载控制器的场景尤其重要。这四项指标最好单独测但实际运行时是互相影响的。比如提高吞吐会让延迟上升、尾延迟变大增大历史深度会提高突发容错但内存占用也会跟着涨。评测方案的本质就是控制变量、分别压测、最后综合观察。另外一个很重要的概念澄清某些场景下搜索“DDS”还会搜到“DDS信号发生器”“直接数字频率合成”这类内容和我这边说的数据分发服务中间件完全不是一回事。前者是数字信号处理技术后者是分布式实时通信中间件。本文所有讨论都限定在中间件范畴不涉及信号发生器方向。2. 三款协议栈的架构差异与选型背景2.1 RTI Connext DDS工业级老大哥RTI Connext DDS在DDS领域属于资历最老、商业化最成熟的一档。航空航天、车载系统、大型工业控制里经常看到它的身影。它的优势在于整套东西非常“完整”QoS策略覆盖极其全面零拷贝传输、多通道、内容过滤、动态发现、监控工具链都很完善。如果项目需要做严格的功能安全认证、需要和已有的Tier1供应链体系对接RTI往往是首选。代价也很直观首先是要购买授权核心模块和额外模块分开计费整体成本不低。其次RTI对运行环境比较敏感在容器或者虚拟化环境里性能损耗明显生产环境往往建议裸金属部署。文档和工具相对封闭出了问题基本靠官方支持社区里能查到的资料有限。2.2 FastDDS伴随ROS2走红的新生代主力FastDDS由eProsima团队维护Apache 2.0开源协议最亮眼的标签是ROS2的默认RMW实现。ROS2生态里大量项目直接跑在FastDDS上所以它和ROS2的集成程度最高用起来最“顺手”。底层传输支持UDPv4、TCP、共享内存SHM消息序列化用的是CDR对跨语言支持和跨平台编译做得都不错。FastDDS的问题在于默认配置相对保守很多参数满足的是“通用性”而不是“最优性能”。如果不去手动调整XML profile里的线程数、Buffer大小、共享内存开关很容易跑出平庸甚至偏后的成绩。线程池模型在端点数增多、连接数增大的场景下CPU占用会明显上升。用一句话概括上限很高但需要会调。2.3 CycloneDDS轻量级与低延迟的代表CycloneDDS是Eclipse基金会托管的老牌项目最初源自PrismTech的Vortex底层采用纯C实现设计目标非常明确极致轻量、低延迟、低资源占用。它对嵌入式平台非常友好同时也是ROS2官方支持的RMW之一用rmw_cyclonedds可以无缝切换。CycloneDDS在事件处理和线程模型上做了大量简化避免了不必要的锁竞争和线程切换因此在中小消息包场景下延迟抖动控制得相当好。短板同样存在工具链生态远不如RTI完整部分高级观测手段需要自己写脚本或依赖第三方工具大消息传输时的吞吐上限需要手动调socket buffer和分段参数否则在高负载下会被RTI和FastDDS拉开差距。为了更直观地对比三款协议栈的定位差异我整理了一份简要表格对比维度RTI ConnextFastDDSCycloneDDS开源情况商业闭源Apache 2.0开源Eclipse开源核心语言C/CCCROS2支持有RMW支持默认RMW有RMW支持资源占用中高中低大包吞吐优秀优秀中上需调参小包延迟优秀中上优秀功能安全认证齐全部分部分主要场景航空航天、关键工业ROS2、机器人嵌入式、实时控制3. 评测环境与基准方案设计如何让结果可复现3.1 硬件与系统基线做DDS评测之前我一直建议先把环境“洗干净”。如果机器上有无关服务、网卡中断没有做亲和性绑定、CPU处于动态调频状态测出来的数据会很脏p99抖动甚至会把不同协议栈的差异完全淹没。我自己用的测试环境是两台x86服务器直连万兆网口操作系统是Ubuntu 22.04内核版本5.15CPU固定在2.4GHz并关闭turbo boost和SMT网卡中断绑定到固定核心MTU设置9000。之所以这么苛刻是因为DDS性能评测本质是在看协议栈实现差异而不是环境噪声。如果要给别人复现这些基线信息必须写清楚。网络链路基线建议用iperf3先跑一遍确认TCP和UDP裸吞吐都达到物理线速。如果iperf3都跑不满说明网卡驱动、队列、中断配置有问题先修环境再测DDS。3.2 测试工具与测试矩阵三款协议栈各自有官方推荐的性能测试工具RTI有Perf TestFastDDS有performance testCycloneDDS官方提供ddsperf。这些工具原理类似都是创建发布者和订阅者然后定时打时间戳统计收发数据。建议优先使用官方工具因为QoS配置和协议栈内部参数对接最完善。测试矩阵至少要覆盖三个维度消息大小、可靠性策略、拓扑关系。我常用的是64B、1KB、64KB、1MB四档消息分别测试BEST_EFFORT和RELIABLE策略下的吞吐与延迟。拓扑方面单对单、一对多比如1到3、多对多比如3到3都要覆盖因为DDS的发现机制和线程调度在不同连接数下差别很大。3.3 统一QoS与典型配置示例跨协议栈对比最怕QoS不一致。不同实现里“默认可靠性”“默认历史深度”差异很大如果不显式统一得出的结论很容易误导人。我固定了两套基准配置BEST_EFFORT场景可靠性BEST_EFFORT历史KEEP_LAST 1不带流量控制。RELIABLE场景可靠性RELIABLE历史KEEP_LAST 10自动ACK间隔和重传缓冲交给各协议栈自己管理。以CycloneDDS为例可以通过URI文件控制网卡绑定和socket bufferCycloneDDS xmlnshttps://cdds.io/config xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttps://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd General Interfaces NetworkInterface nameenp3s0 priority1 / /Interfaces AllowMulticasttrue/AllowMulticast DontRoutetrue/DontRoute /General Internal Watermarks WhcHigh500000/WhcHigh WhcLow400000/WhcLow /Watermarks /Internal /CycloneDDS这里Watermarks控制发送高水位和低水位直接影响内存占用和背压触发时机。FastDDS则是在XML profile里设置发送/接收buffer大小和启用共享内存传输profiles xmlnshttp://www.eprosima.com/XMLSchemas/fastRTPS_Profiles transport_descriptors transport_descriptor transport_idudp_transport/transport_id typeUDPv4/type sendBufferSize1048576/sendBufferSize receiveBufferSize1048576/receiveBufferSize maxMessageSize65000/maxMessageSize /transport_descriptor /transport_descriptors /profilesRTI则通过NDDS_QOS_PROFILES.xml配置核心是transport_builtin里的message_size_max和participant内存管理参数。这里不把每个细节展开后面会单独讲调参要点。4. 实测数据与结果分析吞吐、延迟与资源占用4.1 吞吐量谁在持续大流量下更稳先放一组在我们的测试条件下得到的数据注意不同硬件、不同版本协议栈结果会有浮动但整体量级可以作为参考。1对1拓扑、RELIABLE、1KB消息大小条件下持续发布5分钟吞吐量大致如下协议栈吞吐量MbpsCPU占用%备注RTI Connext DDS 6.1.2512063数据裸吞吐接近线速FastDDS 2.14496071默认配置下线程开销偏大CycloneDDS 0.10.5455038吞吐略低但CPU最省换成1MB大包持续发送时差距会进一步拉开。FastDDS在合理调优后利用大消息分段和DDSI-RTPS重组优化吞吐能追近RTICycloneDDS如果保持默认socket buffer吞吐会明显偏低需要手动调大Watermarks和UDPSocketBuffer大小否则容易触发背压丢帧。一个值得注意的现象是64B小包吞吐测试中三款协议栈的“消息条数每秒”都很快接近网卡小包处理上限差距不大。这说明小包场景瓶颈在网络栈和系统调用协议栈本身很难拉开绝对差距真正的分水岭在中等数据包和混合负载场景。4.2 延迟与p99抖动实时系统最在乎的测量延迟测试我采用回环计时方式也就是发布者在消息里写入时间戳订阅者收到后记录当前时间并计算差值再通过单独的回传通道把延迟采样发回发布端统计。为了减少时钟同步误差先跑单机双进程回环然后再跑双机场景做交叉验证。空闲负载下1KB消息、BEST_EFFORT策略双机直连的典型延迟数据大致是这样协议栈p50usp99usp999usRTI Connext5882135FastDDS70108210CycloneDDS5276120在增加背景流量链路带宽占用到50%左右之后RTI和CycloneDDS的p99上升幅度都还算平缓FastDDS的p999会明显上探。主要原因在于FastDDS的线程池模型在高负载下会出现排队效应如果顶层发送频率和接收频率接近线程切换和锁等待就可能把尾延迟拉高。这里想特别提醒一句如果只比较平均延迟而忽略p99和p999很可能会得出“三款差不多”的结论进而选错方向。对实时控制来说100微秒的均值也许都能接受但如果有千分之一的消息延迟跑到3毫秒就可能导致控制周期超时。4.3 CPU与内存占用不是只看快不快在稳定发布500条/秒、1KB消息、RELIABLE场景下我额外统计了进程的CPU占用率和RSS内存。CycloneDDS的内存占用最省参与节点稳定后RSS在80MB左右CPU占用在发布端维持在15%-20%之间。FastDDS的内存受SHM和端点数量影响很大单对单场景RSS在130MB上下CPU占用在25%左右如果创建大量主题和端点内存和CPU都会同步上涨。RTI启动后的基础内存较高大概在180MB以上但稳态很稳CPU波动较小在复杂QoS场景下不容易出现尖峰。从这个维度看如果项目跑在工控机或者汽车域控制器上CycloneDDS的轻量优势非常明显。RTI则适合基础资源富余、追求稳定性的关键系统。FastDDS处于中间位置但一定要把内存模型吃透别在低配设备上直接用默认配置。5. 从实测结果反推实现原理差距是怎么来的5.1 关键路径上的实现差异实测差异背后是三个协议栈在收发关键路径上的设计取舍完全不同。CycloneDDS采用极简的poller线程模型尽量避免多线程竞争收到网络包后直接在IO线程里处理不做额外的工位交接所以延迟低且稳定。它的代价是当CPU核心不足、IO线程被打满时吞吐提升空间受限。FastDDS采用事件驱动加线程池灵活性和并发度高但在高频率小消息场景下线程池的调度开销反而成为瓶颈。FastDDS的共享内存传输在单机场景确实很有优势但跨主机传输时失去SHM加成性能回落明显。RTI的内部实现没有完全公开但从长期使用和性能数据反推它在缓冲区预分配和批量收包上做了大量优化内存管理很“精”对系统调用的次数控制也比一般实现更狠。再加上零拷贝传输选项大包高吞吐场景下自然占据优势。5.2 发现协议与扩展性的隐藏成本很多评测只关注运行期吞吐延迟却忽略发现阶段的差异。实际上在大规模组网场景下发现协议的开销往往是影响系统稳定性的隐性因素。DDS的发现机制基于SPDPSEDP每个新节点加入都要广播自己的Participant信息并交换所有端点的QoS信息。假设系统里有100个节点、每个节点有几十个Topic光发现报文就要进行上万次匹配。三款协议栈在这一块的处理策略差异很大RTI对远端端点信息有缓存和增量机制减少重复处理CycloneDDS提供发现数据合并配置FastDDS则相对依赖标准流程在极端规模下更容易出现“后加入节点很慢才收到数据”的情况。如果对启动时间有严格要求的项目可以调整发现周期、关闭不必要的多播探测、或者改用静态端点发现。这三种协议栈都支持手动指定对端地址启动时间能从秒级压到百毫秒级。5.3 QoS不是玄学可靠性、历史深度与流控怎么影响性能我对这三款协议栈印象最深的一点是QoS参数对性能的影响往往比切换协议栈还大。可靠性RELIABLE模式下发送端要保留所有未确认消息的缓存等待接收端ACK这段缓存大小直接决定吞吐和内存的平衡点。历史深度KEEP_LAST调大能容忍突发但内存和恢复时间同步上涨。流控策略则决定消息是以匀速还是以突发形式发出影响应对背压的能力。所以在固定QoS之前先想清楚业务需求如果是传感器周期数据BEST_EFFORT加KEEP_LAST 1往往最合适如果是控制指令或者状态切换RELIABLE加KEEP_LAST 5通常更稳妥。不要为了“稳妥”把所有Topic都打成RELIABLE性能和延迟代价可能比想象中大几倍。6. 常见问题与调优实战经验6.1 为什么你的测试数字和别人差那么多我经常被问到一个问题“同样一套代码我测出来的数字怎么和某篇文章差一倍”绝大多数情况下差异来自变量没有被控制住。常见的干扰项包括CPU动态调频导致高负载时降频网卡中断和DDS线程抢核测试机器上有其他进程抢占带宽MTU没有统一QoS配置不一致测试工具统计口径不同有的从write调用开始计时有的从序列化之后开始计时甚至有的计算了回调处理时间。建议每次评测前先跑一遍iperf3获取链路基线之后检查CPU频率是否稳定在同一个档位再检查网卡队列数量与RPS配置。环境基线不稳定任何协议栈对比都缺乏可信度。6.2 三个值得注意的“坑”第一个坑是FastDDS的共享内存传输。默认配置下单机多进程通信会走SHM跨主机才走UDP。有人在本机测试FastDDS获得很高吞吐然后拿这个数字去对比跨主机的其他协议栈结果完全不公平。如果目标是测跨主机UDP性能务必把SHM关掉如果目标是测单机性能则要注明传输模式。第二个坑是RTI在虚拟化环境里的表现。RTI对系统调用路径的优化很敏感容器环境下网卡中断和系统时钟会引入额外抖动p99可能比裸金属翻倍甚至更多。生产环境要么给RTI专用裸金属节点要么使用SR-IOV直通网卡对性能要求高的系统不建议跑在通用K8s节点上。第三个坑是CycloneDDS在某些内核版本下依赖eventfd/poll路径系统调用次数略多延迟会上浮。解决办法是调大socket buffer减少唤醒次数同时绑定网卡中断到固定核心实测能明显改善p999。6.3 提升测试可复现性的检查清单如果你准备自己跑一轮完整评测我建议按这个顺序操作关闭CPU动态调频固定频率关闭SMT避免邻居线程干扰。关闭防火墙和无关服务确认网卡驱动版本稳定。配置MTU 9000并确认交换机/网线支持直连一般没问题。用iperf3确认TCP和UDP裸吞吐都达到物理线速。统一三款协议栈的QoS参数写进各自的配置文件并校验生效。先跑单机回环测延迟再跑双机测吞吐和长稳。每组测试循环多轮取中位数、p99、p999不要只看单次结果。这套流程跑下来得出的数据才有说服力也方便后面做性能回归。7. 选型建议性能之外还要看什么7.1 不同落地场景的推荐倾向测试数据能帮我们判断能力边界但选型绝对不只是看数据。基于长期项目经验我会这样建议对功能安全要求高、资金充足、供应链生态固定的航空航天和关键工业项目优先RTI。它的认证资料完备工具链最齐全长期维护风险最低。ROS2项目、机器人原型验证、需要快速迭代的团队FastDDS最省心和ROS2生态结合最好社区活跃度高。嵌入式控制器、资源受限平台、对延迟和资源占用极其敏感的场景CycloneDDS是首选轻量且稳定。大规模节点组网、复杂QoS混合场景RTI仍然有优势如果用开源路线建议重点调CycloneDDS的发现策略和线程绑定也能达到接近可用的性能。7.2 一个让我印象深刻的选型案例去年做一个移动机器人底盘控制项目时早期用的FastDDS默认配置跑起来CPU占用一直在40%左右而且高频控制指令的p99偶尔会跳到几毫秒。后来换到CycloneDDS并做了网卡绑定、socket buffer调优同样一套控制逻辑CPU回落到20%以下尾延迟也稳定了很多。这个项目让我深刻意识到协议栈本身没有绝对的优劣关键是匹配场景、吃透配置。7.3 如果你准备自己跑一轮评测我的建议我的建议是先不要急着选边站花一个周末把三款协议栈都装上按上面的检查清单跑一遍。没有百分百“最好”的DDS实现只有“最适合当前系统约束”的中间件。评测也不是一锤子买卖协议栈版本迭代很快性能排名可能半年就变一次建议给自己留一个定期复测的机制——把这些测试脚本保存下来下次升级版本后重跑一遍比任何博客里的结论都要靠谱。