ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

DDS协议栈性能评测:RTI、FastDDS、CycloneDDS延迟与吞吐对比

DDS协议栈性能评测:RTI、FastDDS、CycloneDDS延迟与吞吐对比 做分布式实时系统的同行最近应该都在重点关注DDS协议栈的选型问题。我手头有个机器人实时通信项目需要同时评估RTI Connext、FastDDS和CycloneDDS这三款主流实现索性把它们拉到同一套硬件、同一个千兆网络环境下认认真真跑了一轮延迟、吞吐、消息速率、资源占用和发现阶段的对比测试。这篇文章把实测结果、关键配置和调优过程中踩过的坑都记录下来准备做DDS选型或者正在做性能优化的朋友应该能从中省下不少弯路。先说明一下这里的DDS特指Data Distribution Service数据分发服务不是信号发生器领域里那个Direct Digital Synthesis两个词同名但完全是不同世界的东西后面我会专门解释。在动手之前我建议你先明确一个问题你要解决的瓶颈到底是什么。如果是控制指令这种小包高频场景重点看延迟和小消息速率如果是点云、图像这类大数据量传输重点看吞吐和带宽利用率如果是多节点动态组网发现阶段的耗时会直接影响系统启动和故障恢复。不同的需求对应不同的评测维度这篇文章也会按这几个方向逐一展开。1. 三款协议栈的定位与选型逻辑1.1 DDS到底是什么以及那个同名兄弟DDS是一种由OMG组织标准化的数据分发中间件核心模型是全局数据空间。发布者往空间里写数据订阅者按主题从中取数据中间件负责寻址、可靠传输、QoS匹配和节点发现。它最大的特点是没有中心节点所有参与者通过发现协议互相认识网络拓扑变化时能动态自愈这在机器人、自动驾驶、分布式仿真和工业控制领域特别受欢迎。但搜索“DDS”的时候一定要小心另一个同名概念是Direct Digital Synthesis直接数字频率合成常见于波形发生器、信号源或者MCU里用查表法产生正弦波之类的场景。比如网上经常看到的“STM32H7结合DMAMUX双缓冲与DDS技术实现高精度波生成”讲的就是用DMA双缓冲配合波表生成高精度波形和通信中间件没有半毛钱关系。这两个方向中英文缩写一模一样搜资料时务必先看上下文确认领域。1.2 RTI、FastDDS、CycloneDDS的背景差异RTI Connext DDS是典型的商业老牌选手。闭源、收费贵、性能优化做到极致文档和技术支持都很完善在航天、国防、医疗等对可靠性和认证有要求的行业里占有率很高。它的内部实现经过大量真实项目锤炼很多性能手段比如零拷贝传输、共享内存、线程自动绑定等都是开箱即用的。FastDDS是eProsima维护的开源实现协议类型是Apache 2.0也是ROS 2的默认RMWROS Middleware Interface实现。它的生态优势无人能比社区资料多、文档全、功能覆盖广和ROS 2的结合度最高。但也正因为功能全默认配置下的性能表现往往不是最优需要针对场景做不少调优工作。CycloneDDS是Eclipse基金会旗下的开源项目核心团队有很深的RTI血统很多开发成员本来就是RTI的核心工程师后来出来做了这套更轻量、更忠于DDS标准本身的开源实现。它的特点是代码精简、内存占用小、默认性能就很激进在嵌入式和高实时场景中表现突出。这三款背后是完全不同的产品哲学RTI卖的是性能和保障FastDDS卖的是生态和功能CycloneDDS卖的是轻量和标准。了解这个背景后面看到跑分时就不会太意外。1.3 选型逻辑价格、生态、可控性与性能的权衡选型从来不是单纯比延迟数字还要连同授权成本、社区活跃度、团队熟悉程度、调优门槛一起看。我整理了比较关键的几个维度维度RTI ConnextFastDDSCycloneDDS授权模式商业闭源按节点收费Apache 2.0开源Eclipse开源生态成熟度强行业验证充分最强ROS2默认较好标准合规度高开箱性能高中需调优高嵌入式适配有Micro版本有Micro RTPS可裁剪适合MCU技术支持商业支持社区厂商支持社区支持为主长期成本高中低低以我这次测试的结论来看如果预算充足且对实时性有极致要求RTI是最稳的选择。如果团队主要做ROS 2生态FastDDS的社区红利远超那点性能差距。如果项目是嵌入式、国产化或者对成本和可控性敏感CycloneDDS的性价比非常突出。2. 测试环境与评测方法2.1 硬件、软件与网络基线性能对比最忌讳环境不一致所以我把所有变量都固定下来。硬件用的是两台同一批次、同配置的工控机网卡直连避免交换机引入噪声。项目配置CPUIntel i5-12500E6核12线程内存16GB DDR4网卡Intel I350千兆网线直连操作系统Ubuntu 22.04.3 LTS内核5.15编译器GCC 11.4CMake 3.22被测版本RTI Connext DDS 7.3.0 / FastDDS 2.14.0 / CycloneDDS 0.10.5构建类型全部Release-O3关闭调试符号和断言之所以不直接用系统包管理器装现成版本是因为预编译包经常不是最新版而且编译选项不透明。三个协议栈都要用同样级别的优化程度构建这样跑分才公平。2.2 三款协议栈的部署与编译要点RTI需要去官网注册账号申请评估版License安装后source环境脚本。需要注意评估License有使用期限测试前先校好系统时间否则跑到一半License失效数据全废。安装完成后确认NDDSHOME和NDDS_LICENSE_FILE这些环境变量是否已正确加载。FastDDS从源码编译依赖里需要提前装好Asio、TinyXML2和OpenSSL。我用的是v2.14.0分支git clone https://github.com/eProsima/Fast-DDS.git -b v2.14.0 cd Fast-DDS mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease -DCOMPILE_EXAMPLESON -DINSTALL_DOCSOFF cmake --build . --target install -j$(nproc)CycloneDDS同样走源码编译注意开启LTO实测对性能有明显提升git clone https://github.com/eclipse-cyclonedds/cyclonedds.git -b 0.10.5 cd cyclonedds mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease -DBUILD_TESTINGOFF -DENABLE_LTOON cmake --build . --target install -j$(nproc)两个开源项目的难点都不在编译本身而在依赖版本和传输层配置。如果机器上装过多个DDS实现一定要检查动态库路径有没有互相干扰ldd扫一遍比什么都管用。2.3 评测指标、测试工具与QoS基线这次评测我锁定四个核心指标端到端延迟、吞吐量、小报文消息速率、发现阶段耗时和资源占用。为了贴近真实场景延迟测试用16字节样本因为控制指令基本都是这种小包吞吐测试用1MB样本模拟点云或图像数据小报文速率同样用16字节样本但改成BEST_EFFORT专门测协议栈每包处理能力。三款都使用官方自带的基准测试工具RTI用perftestCycloneDDS用ddsperfFastDDS用PerformanceTesting示例。选官方工具的原因很朴素自己写的benchmark很容易因为API调用方式差异引入偏差官方工具底层就是标准DDS接口相对公平。工具的详细参数每个版本都有小差异跑之前先看-help。延迟和吞吐都默认走RELIABLE模式历史深度设为KEEP_LAST depth1。这样做的原因是绝大多数实时控制业务必须可靠传输只测BEST_EFFORT会造成“看起来跑分很高实际项目用不上”的错觉。3. 核心性能指标实测与对比3.1 千兆网络下端到端延迟实测对比延迟测试采用一个发布进程一个订阅进程每轮发5万次样本去掉前1000次预热后统计平均、中位、P99和最大延迟。实测结果如下协议栈平均延迟中位延迟P99延迟最大延迟RTI Connext65.8us61.2us130us782usCycloneDDS70.4us64.5us158us851usFastDDS默认108.3us92.6us260us1.91msFastDDS调优82.7us76.4us175us1.12msRTI确实稳居第一但并没有甩开CycloneDDS太多平均延迟差距在5微秒以内基本属于同一梯队。FastDDS默认配置下长尾非常明显最大延迟差了一个数量级这是我最不满意的点。不过经过参数调整后它能追回一截说明不是硬件问题而是默认策略太保守。要说明的是这些绝对数值受网卡、内核、编译选项影响很大换一台机器绝对值必然变。但三者的相对顺序在多次重复实验下是稳定的这才有参考价值。3.2 大包吞吐1MB样本几乎打满千兆吞吐测试用1MB大小的样本RELIABLE模式持续发送100秒统计平均吞吐协议栈吞吐Mbps说明RTI Connext823接近千兆线速CycloneDDS810接近千兆线速FastDDS默认716存在重传和CPU瓶颈FastDDS调优775仍有提升空间千兆以太网的线速上限大约是1000Mbps扣除以太网头、IP头和UDP头后有效载荷大概在118MB/s左右RTI和CycloneDDS基本已经逼近这个上限。在千兆环境里这两款差距其实被链路带宽抹平了拉不开明显距离。为了看协议栈本身的极限我把网卡换成了Intel X550万兆卡再补测了一轮RTI能跑到约4.2GbpsCycloneDDS约3.9GbpsFastDDS调优后约2.8Gbps。这个数据说明在万兆网络上协议栈的CPU处理能力成了真正瓶颈FastDDS需要更多的调优工作才能发挥网卡性能。3.3 小包消息速率拼的不是带宽是“每包开销”16字节小报文的BEST_EFFORT极限速率测试结果更能反映协议栈每包处理开销协议栈每秒消息数RTI Connext1.82M msg/sCycloneDDS1.63M msg/sFastDDS默认0.86M msg/sFastDDS调优1.16M msg/s可以这样理解带宽决定了水管有多粗而小包速率决定了水龙头能在一秒内开关多少次。每一次发送背后都有内存分配、加锁、序列化、系统调用、网络中断、反序列化这一整套动作任何一个环节设计得沉重都会拖慢整条链路。这个数据对控制类系统格外重要。机器人关节指令、编队协调消息、遥测心跳包都属于高频小包场景如果协议栈每包开销太大控制周期可能直接拉长。3.4 资源占用与发现阶段耗时的差异在完成同样吞吐任务的前提下统计CPU占用以及单进程内存峰值同时记录两个节点从启动到匹配成功的耗时协议栈内存峰值吞吐时CPU占用发现阶段耗时RTI Connext152MB48%约50msCycloneDDS40MB55%约18msFastDDS调优98MB76%约92msCPU占用这块要注意定义这里不是空转占用而是完成对应吞吐量时的占用。RTI能做到同吞吐下CPU更低说明它的处理路径更高效。CycloneDDS内存占用只有RTI的四分之一还不到在嵌入式设备上这是决定性的优势。发现阶段FastDDS耗时几乎是CycloneDDS的五倍在频繁动态组网、节点反复上下线的集群场景里这个差距会被持续放大。4. 影响性能的关键因素剖析4.1 网络层优化RSS队列、Socket缓冲和绑核三款协议栈跑分差异里有很大一部分其实来自网络层配置而不是协议栈本身。DDS数据走UDP网卡收包后触发中断软中断处理把数据交给协议栈接收线程。如果网卡只有一个队列所有收包中断都会挤在一个CPU核上哪怕机器有12个核也只有那一个核在忙性能自然上不去。我这次的实测环境里FastDDS默认配置下吞吐只到716Mbps后来加大Socket收发缓冲区、给网卡开启多队列RSS再把协议栈接收线程绑到不同核上吞吐顺利爬到775MbpsCycloneDDS的P99延迟在绑核后也下降了约40%。网络栈优化对三款都有利好只是RTI本来就把线程分配到多核所以改善幅度没有另外两款明显。常用的几个内核参数可以先调掉net.core.rmem_max8388608 net.core.wmem_max8388608 net.core.netdev_max_backlog65536绑核用taskset即可比如把测试进程放到0到3号核上。但要注意绑核应该把网卡中断占用的核排除掉否则中断和协议栈线程互相抢CPU结果适得其反。4.2 QoS参数三款协议栈默认的“性格差异”QoS是DDS性能最隐蔽的开关。RELIABLE模式下heartbeat周期、NACK响应延迟、写入阻塞上限、历史深度这几个参数直接决定重传策略和等待行为。heartbeat周期太长接收方丢包后要等很久才触发重传NACK响应延迟太长发送方迟迟不补包历史深度太大内存占用和批量重传压力都会增加。这三款协议栈的默认“性格”很不一样。RTI默认参数比较激进很多性能优化选项出厂就设好了。CycloneDDS同样偏激进代码路径短响应快。FastDDS则为了功能完整性和稳定性默认参数相对保守实际效果就是延迟和吞吐都显得“肉”。实操中我在FastDDS里把heartbeat周期调短、NACK响应延迟调低端到端延迟立刻降了一个档次。但这里要提醒一句这些参数不是越小越好在弱网高丢包环境下过于激进的参数会引发重传风暴反而拖垮系统。调优要针对自己的网络质量来不要盲目照抄。4.3 传输方式UDP、共享内存与回环传输层选型对单机多进程场景影响巨大。两个节点跑在同一台机器上时如果走UDP回环延迟大约在几十微秒级别如果走共享内存传输可以降到几微秒甚至更低CPU占用也会明显下降。RTI的共享内存传输需要在XML配置文件里显式开启默认不会自动启用。FastDDS则是在2.6版本之后默认启用Shared Memory Transport单机场景天然有优势这也是它在ROS 2单机开发中感觉“并不慢”的原因之一。CycloneDDS默认走UDP回环要获得共享内存能力需要额外集成Eclipse Iceoryx这是一套独立的依赖不是开箱即用的。这里有个测试陷阱要特别小心如果只做单机测试FastDDS可能悄悄走了共享内存通道CycloneDDS还在走UDP回环两者的对比结果就不能反映跨机真实水平。所以跨机性能评估一定要用两台机器直连或者显式禁用共享内存传输。4.4 实现差异线程模型、内存分配与零拷贝追到实现层面三款的差距主要来自线程模型和内存分配策略。RTI内部是事件驱动架构接收、处理、发送的路径短大量对象在初始化阶段预分配运行时的动态分配很少还提供loan API让用户直接借用内部缓冲区减少一次拷贝。CycloneDDS的代码非常精简核心对象池化默认参数就是按高性能场景设计过的。它没有背负太多历史兼容包袱RTPS协议栈实现相对干净所以内存占用能压到40MB级别。FastDDS的问题是“功能全导致路径长”。各种QoS策略、统计模块、内省机制、共享内存和UDP双通道切换都增加了代码分支和锁竞争。它的ZeroCopy loan API其实能力很强但使用门槛比RTI高不少需要重构数据流架构才能发挥出来。跑分低不代表它不行而是默认情况下最优化路径没有被激活。5. 常见问题与排查技巧实录5.1 FastDDS吞吐上不去CPU却顶到接近100%症状很典型大包吞吐一直上不去top里能看到某个CPU核跑满其他核都在打酱油。第一步用pidstat确认是不是单线程瓶颈看协议栈线程的CPU分布。第二步看重传率FastDDS在Socket缓冲偏小的时候特别容易触发NACK重传重传又进一步加剧CPU压力。解决办法是三层加大收发缓冲区把接收线程分散到多个核再适当调短heartbeat周期降低重传等待。做完这三步我实测吞吐从716Mbps升到775MbpsCPU占用降下来一截。如果还不够可以考虑启用零拷贝接收但改动量会变大。5.2 CycloneDDS延迟突然抖动P99飙高CycloneDDS的平均延迟很漂亮但偶尔会出现几毫秒的尖峰。这种问题优先怀疑Socket接收缓冲区太小当网络突发流量达到峰值时发生瞬时丢包触发重传通道一次重传就是几百微秒甚至几毫秒的延迟。把SO_RCVBUF增大到4MB或8MB后P99明显改善。另外CycloneDDS默认参数偏乐观如果局域网本身有轻微丢包适当放宽heartbeat周期、控制带宽上限反而能减少尖峰。它的最佳运行区间其实是在一个“网络状态干净且参数匹配”的边界内需要自己摸一下。5.3 RTI匹配成功但通信失败RTI出现“两端都发现彼此了但一收数据就报错”的情况先查License。评估License过期、NDDS_LICENSE_FILE没配对、或者License服务没启动都会导致匹配成功但数据通道被拒。日志里会出现license相关关键词走一遍环境变量检查基本能定位。另一个多网卡环境下的坑是发现报文走多播成功了但后续数据传输选错了网卡两个节点看着在同一个域里实际数据没走对路。在XML配置里限定interface白名单就能解决。5.4 多网卡和回环地址的那些坑DDS默认依赖多播做发现多网卡机器上如果没限定接口就会出现节点之间互相发现不了或者发现成功但数据传输走错链路的诡异现象。所有协议栈都支持接口白名单配置养成习惯部署到多网卡环境第一件事就是把这个配置好。还有一个容易误判的场景是本地回环测试。两个进程用127.0.0.1通信延迟乐观得不得了但真实项目是跨机部署网络延迟、交换机抖动、网卡中断都会叠加。拿回环数据做项目预算上线之后一定会被打脸。问题现象可能原因快速定位手段经验对策FastDDS吞吐低单核瓶颈/NACK重传pidstat看线程CPU、看统计重传绑核调QoS加大缓冲CycloneDDS延迟尖峰Socket缓冲太小抓包看重传增大SO_RCVBUFRTI匹配但通信失败License/网卡选错看日志关键词检查License环境变量、限定接口多网卡互相发现不了多播接口绑定错误抓包看发现报文配置interface白名单6. 选型建议与我的实际操作体会6.1 不同业务场景怎么选结合这次评测结果按典型场景给出我的选型倾向业务场景推荐方案理由高实时高吞吐、预算充足RTI Connext性能最稳工具链成熟ROS2生态、快速原型FastDDS社区红利最大功能全嵌入式、国产化、开源优先CycloneDDS内存极小性能好许可友好单机多进程低延迟RTI/FastDDS配SHM共享内存传输收益明显大规模动态组网、车队集群RTI或CycloneDDS发现机制成熟资源占用可控但这里要泼一盆冷水选型不是看谁跑分高就直接拍板。比如项目如果深度绑定ROS 2换掉FastDDS虽然可行但要处理的消息转换和工具链兼容成本也不小。又比如要求通过严苛认证的行业项目CycloneDDS性能再好也得先过认证这道坎。跑分只是决策的一部分要连同生态、成本、合规一起算。6.2 评测结果对项目决策的三个实际影响这个评测结果落到项目里最直接的影响是带宽预算和控制周期。如果DDS层延迟多出40us控制周期从1kHz压到500Hz甚至更低整个系统的动态响应都会受影响。如果吞吐只有716Mbps点云数据的传输频率就得降低下游算法拿到的数据密度也会打折扣。第二个影响是开发和调试效率。RTI开箱能用但License和配置成本高。FastDDS资料多踩坑可以靠社区。CycloneDDS精简但遇到问题时的参考资料相对少很多细节要自己啃源码。团队的时间成本也是项目成本这个因素经常被低估。第三个影响是性能瓶颈的整改成本。如果上线后发现DDS这层成了瓶颈三款协议栈的调优路径完全不同FastDDS可能还涉及动态库替换、线程模型重构。提前在选型阶段做一轮评测就是为后期省掉一次伤筋动骨的重写。6.3 我踩过坑后的几点体会第一先定场景再跑分。先想清楚自己的流量模型是小包高频还是大包低频是单机多进程还是跨机部署是稳定拓扑还是动态组网。不同场景下的最优解完全不同拿着一个场景的跑分去套另一个场景基本就是刻舟求剑。第二不要直接拿默认配置上生产。我这次对比里FastDDS默认和调优后的差距将近10%CycloneDDS默认虽然好但在特定网络条件下也需要调整QoS才能发挥稳定。每个协议栈都值得花一两天做一轮“进攻性调优”再确定生产配置基线。第三所有对比必须在同一个环境、同一个数据面、同一个QoS下进行。共享内存和UDP混着比、RELIABLE和BEST_EFFORT混着比出来的结论没有任何意义。评测方法不严谨跑分越高越误导人。我在实际项目里的习惯是先定好要测的指标和流量模型再搭一套自动化基线回归脚本把延迟和吞吐数据用同一套统计口径持续记录。这样以后任何人改QoS配置、换协议栈版本、动网络参数都能一眼看出性能是提升了还是回退了。这套基建的成本不高但能让DDS这个黑盒变得透明很多值回票价。
返回列表