实验速度

1. via topic

上图是以前ROS课上做的一个实验,内容是测试一个publisher和一个subscriber之间通讯所用的时间。两个node都很简单,publisher发送一个字符串,字符串带有标号;subscriber回显该字符串,字符串长度不超过20个char。

怎么去标定发送时间是接收时间呢?目前使用的方法就是在publisher发送前使用ROS_INFO输出一个消息,消息会带有ROS的时间戳;subscriber的callback函数里边也使用ROS_INFO输出一个带时间戳的消息。虽然说这种方法并不是非常精准,但目前也没有想到更好的办法了,哪怕是使用header里边的time stamp也有一个获得当前时间和赋值的过程,难以百分百精确,所以目前只能这样粗略测量。

根据实验数据可以发现在同一台机器上,两个node通过topic通讯,大致产生0.7ms的延迟。(本人机子i5-3210M/4G)

2. via service

这张图是今天自己做的测试,可以看到平均时间大约在3ms左右。

测量的方法也是跟上面的类似。Client在call之前先输出一个带时间戳的消息,server在接收到请求执行操作前也会输出一个带时间戳的消息。这次client与server之间传递的消息更短,是两个int。

从上图我们不难发现,通过service通讯居然比topic延迟要高?实在是不愿意相信,因为这跟我一开始的理解是相违背的。为了控制实验环境平台的一致性(我从groovy换到了indigo),于是重做了以前的那个实验,粗测通过topic传输的延迟时间,发现依然是0.7ms左右。


理论速度

为何前面的实验结果让我如此惊讶?

官方文档中写明,client与server之间维持着一个持久连接。对于这种RPC请求/回复机制,官方给出的评价是“面对低鲁棒性的服务程序变更有着更好的性能表现”(higher performance at the cost of less robustness to service provider changes)1

说到持久连接,不禁让人想起ROSTCP。照这么说,如果在ROS架构下node之间通讯的底层实现都是通过ROSTCP/ROSUDP的话,那理应via service应该跟via topic的速度相当,如果将“持久性”纳入考虑范围的话,service甚至应该比topic更快一些才对。但实际情况是via service的时延是via topic的4倍左右。如此大的差距,实在让人百思不得其解。


实现机制——同步与异步

其实在开始写这篇博文的时候,我都依然没有想明白这个问题。边写边查资料,看到ros answer上一位大大在描述这两种机制时,用到了asynchronous和synchronous这两个字眼2。回到宿舍一边洗着冷水澡一边在想,忽然灵光一现!是的,实验的结果是没有问题的,有问题的是我的实验方法!

- Asynchronous Topic

Topic是异步的。简简单单的一句话,里边却隐含了千言万语。让我关注起这一点的原因除了ros answer上面的那篇问答,还有一个就是自己做的另一个实验:创建一个publisher,pub的速度是100Hz,发送缓冲区的大小只有1;创建一个subscriber,调用callback函数的的速度是1Hz(用spinOnce),但接收缓冲区的大小是1000。这样的效果就是,publisher近乎匀速地发送着数据,每秒100次;而subscriber每一秒调用一次callback函数(spinOnce),每次调用都一次性地处理接收缓冲区内的所有数据。由于接收缓冲区大小远大于发送频率,所以接收缓冲区不存在满的情况,所以就能看到subscriber每秒都会很快地处理完100条消息,然后进入休眠,再被唤醒执行callback,再休眠……

而之前用于测试的subscriber,我使用的是spin。这也就意味着,回调函数一直是处于类似于忙等待的状态的,一旦发现接收缓冲区内有数据,即刻取出作运算(前提当然是获得CPU分片时间)。这也就说明了为什么实验得出的结果via topic会更快!但要注意了,忙等待是会占用硬件资源的。在这种简单的实验条件下,via topic固然是很快,但当一个大项目跑起来时,它之前的高性能表现可能要大打折扣。

- Synchronous Service

至于server,在基于RPC请求/回复机制的前提下,它在接收到调用请求前都是处于休眠状态的。Client的call请求将server唤醒,然后server执行请求,再返回结果给client。所以之前在计时的时候,大部分的时间都是消耗在将server从休眠状态唤醒上了!所以才会看起来比via topic慢。

分析到这里,我就在想,那真正的client与server之间通讯的时延,是不是可以利用server返回结果给client这段时间算出呢?这才是真正抛开了将server从休眠唤醒的时间影响,是client与server通讯的真正时延!于是又有了下图: 

果不其然!表中数据的中位数应该在0.3ms左右,也就是说,从server返回结果到client接收到结果,只需要0.3ms的时间!尽管使用spin通过topic转发数据类似于忙等待(也许ROS的内部机制会对spin的频率作最高限制),但也需要大约0.7ms的时间!而service机制中,client发出call请求之后就会进入阻塞状态,直至server返回结果,期间的时延是via topic的一半而已!

而从这个数据我们还可以估计出将休眠状态的server唤醒,所需要的时间大约是2.7ms。如果计算一来一回,client从发出call请求到接收返回结果,除去请求被执行的时间,在通讯上耗费的时间约是3.3ms,其中将server唤醒的时间约占82%!

- Conclusion

Topic与Service各有优劣。在设计项目的时候,要周全考虑各个方面的因素。Service比较适合用于执行复杂的、调度次数较低的任务。而topic则适合在通讯频率高的情况下使用。再者,使用ros::Rate和sleep合理设置程序的执行速率,能使程序弹性更大,增强可维护性。使用topic时,也别忘了关注一下缓冲区的大小设置。


优劣分析

Service

- 优点:

  • Client只需要关注发出命令请求、接收反馈,而无须关注底层实现,系统可维护性高
  • Client维护着一个与server的持久连接(persistent connection),在单纯的数据传输上可以做到更快,尤其是在分布式作业时

- 缺点:

  • 当server单方改变执行模式或者存在bug的时候,client无法得知具体情况,因为server程序对client而言是透明的。在这种情况下,client只能得到一个错误的数据,或者被告知执行失败,甚至是等待超时
  • Server唤醒耗时太大,不建议用于通讯频率高的情况

Topic

- 优点:

  • 能非常方便地通过监听topic的方法查看各个node的运行状态等信息,可维护性高
  • 能根据实际情况调整发送速率、发送/接收缓冲区大小,使之适应项目需求
  • Topic是多对多的,可操作性强;而service只能一对多(一个server应对多个client)

- 缺点:

    • 因为是异步架构,回调函数的执行频率设计对系统整体性能影响很大
    • 对于使用频率不高的程序,若使用topic进行信息交换,想要减少额外系统开销的办法就是降低回调的速率。但一旦降低回调的速率,同时受到负面影响的还有系统的实时性

【转】ROS之topic和service通信比较的更多相关文章

  1. ROS(二)Service通信

    使用自定义的消息类型,实现service方式的节点间双向通信 在package目录下创建msg和srv目录,存放package需要使用的.msg和.srv文件. 在ROS中,message被设计为一种 ...

  2. ROS Node/Topic/Message/Service的一些问题

    1.Node http://blog.exbot.net/archives/1412 (摘自老王说ros) node干的什么活?callback queue里的活.这个callback queue里的 ...

  3. ROS学习(七)—— 理解ROS Topic

    一.准备工作 1.打开roscore roscore 2.turtlesim 打开一个turtulesim节点 rosrun turtlesim turtlesim_node 3.turtle key ...

  4. Service通信

    1.简介 Service通信是双向的, 它不仅可以发送消息, 同时还会有反馈. 所以service包括两部分, 一部分是请求方( Clinet) , 另一部分是应答方/服务提供方( Server) . ...

  5. 为应用程序池“XX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误

    场景 WCF应用程序部署在IIS7中,使用net.tcp协议对外给几百台客户端提供服务,应用程序池不断崩溃重启. 分析过程 在事件查看器中看到的错误信息类似于 为应用程序池“XX”提供服务的进程在与 ...

  6. 通过AIDL在两个APP之间Service通信

    一.项目介绍 [知识准备] ①Android Interface definition language(aidl,android接口定义语言),其目的实现跨进程的调用.进程是程序在os中执行的载体, ...

  7. [转帖]为应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。

    [终极解决方案]为应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误.该进程 ID 为“XXXX”.数据字段包含错误号. ...

  8. IIS 为应用程序池提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误的解决方法

    系统环境:Windows Server 2008 R2 64位, IIS 7.0 错误信息: 为应用程序池提供服务的进程在与 Windows Process Activation Service 通信 ...

  9. Activity与Service通信

    Activity与Service通信的方式有三种: 继承Binder类 这个方式只有当你的Acitivity和Service处于同一个Application和进程时,才可以用,比如你后台有一个播放背景 ...

随机推荐

  1. flutter环境部署

    一,xcode开发环境配置问题记录 1,Signing for "Runner" requires a development team xcode需要配置AppleID: 1,X ...

  2. Spring Boot中的静态资源文件

    Spring Boot中的静态资源文件 1.SSM中的配置 2.Spring Boot 中的配置 2.1 整体规划 2.2 源码解读 2.3 自定义配置 2.3.1 application.prope ...

  3. flutter--Dart基础语法(三)类和对象、泛型、库

    一.前言 Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,Flutter 开源.免费,拥有宽松的开源协议,支持移动.Web.桌面和嵌入式平台. ...

  4. 图的深度优先遍历算法(DFS)

    搜索算法有很多种,本次文章主要分享图(无向图)的深度优先算法.深度优先算法(DFS)主要是应用于搜索中,早期是在爬虫中使用.其主要的思想有如下: 1.先访问一个节点v,然后标记为已被访问过2.找到第一 ...

  5. centos 7 部署nginx及libfastcommon

    1.编译环境 (centos)yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib- ...

  6. Scala数据结构(数组,Map和Tuple)

    package com.zy import scala.collection.mutable import scala.collection.mutable.ArrayBuffer object te ...

  7. AtCoder Beginner Contest 176

    比赛链接:https://atcoder.jp/contests/abc176 A - Takoyaki #include <bits/stdc++.h> using namespace ...

  8. Windows10与虚拟机中CentOS-7.2进行ftp通信

    首先Linux的IP地址可以通过以下命令获取: ifconfig Windows10上面IP地址通过下面命令获取 ipconfig 你首先要保证你的主机和Linux虚拟机是可以ping通的(ping都 ...

  9. poj 1410 (没做出来,记得闲着没事看看这道题)

    听说这道题是个大大的坑题 结果wa了十多发,,,,还是没找到原因 #include<cstdio> #include<cmath> #include<algorithm& ...

  10. UVA442 矩阵链乘 Matrix Chain Multiplication

    题意: 这道题也是在不改变原序列每个元素位置的前提下,看每个元素与他身边的两个元素那个先结合能得到最大的能量 题解: 很明显这是一道区间dp的题目,这道题要断环成链,这道题需要考虑在这个区间上某个元素 ...