ROS 2执行器决定何时在可用线程上运行准备回调。回调组限制哪些回调可以同时执行。因此,当工作停留在一个互斥组中时,多线程执行器几乎可以表现出串行行为,而重入组则可能暴露不安全的共享状态访问。
机器人时序失败通常表现为过时的传感器数据、延迟的控制定时器或服务被阻塞。原因可能是回调执行、执行前等待时间、锁、同步服务使用或中间件队列。仅靠线程计数无法确定瓶颈。
本指南应与 ROS 2 实时控制指南 及 ROS 2 QoS 指南一起使用。在更改配置前,先追踪已部署的执行程序。
把执行器(Executor)当作回调调度器来对待
订阅、定时器、服务、客户端和等待任务在准备好时成为可执行回调。执行者等待工作,选择符合条件的回调,并根据其实现和回调组规则调用。它不会自动推断机器人需要处理哪些工作。
列出每个回调的预期速率、最大执行时间、共享资源和截止日期。包含同步客户端或Future对象使用的隐藏回调。不完整的库存使得死锁分析和响应时间声明不可靠。

单个线程使阻挡变得可见
单线程执行器一次执行一个回调。长镜像回调,阻断磁盘写入或服务等待,会延迟该执行程序中每隔一次回调。这种简洁性对于确定性分析非常有用,当最坏情况的综合工作负载能够满足时。
分别测量准备开始等待和从开始到结束执行的准备程度。如果定时器开始较晚,定时器回调可能较短,而另一个回调拥有线程。当一个阻塞调用造成延迟时,平均CPU利用率可能保持较低。
| 症状 | 很可能的层 | 第一次测量 | 共同原因 |
|---|---|---|---|
| 所有回调均暂停 | 单执行线程 | 回调时长 | 阻断I/O |
| 只有一组进行连载 | 回拨组合 | 组和线程跟踪 | 默认组 |
| 服务呼叫挂断 | 依赖循环 | Future对象与回调组归属 | 自死锁 |
| 新消息迟到了 | 队列或执行者 | 回调时的样本年龄 | 慢消费者 |
| 在高负载下错过截止日期 | 排程与竞争 | 尾部等待时间 | 共享锁或CPU压力 |
多线程并不保证并行回调
多线程执行器可以在多个线程上运行合格的回调,但调用组的限制仍然适用。如果所有实体都使用节点默认的互斥组,即使存在多个执行线程,它们也无法并行执行。
在实体创建时检查组分配,并确认该组仍与执行者关联。当前 ROS 2 执行器概念 应被读取用于部署的发行版,因为实现行为可能会演变。
保护序列使用互斥群
互斥的回调组防止其回调同时运行。这可以保护非线程安全状态而无需单独锁,并保持组内的顺序假设。但也可能导致无关的长时间工作,延迟关键计时器。
按实际并发需求进行组回调,而非单纯按节点。将必须序列化的设备事务放在一起,并在共享状态设计允许时分离独立遥测或昂贵的处理。记录每个组为何是互斥的。

重入组需要线程安全代码
重入组允许回调,包括同一回调的多个实例,重叠。它可以改善独立工作的并发性,但不能使访问的库、缓冲区或设备线程安全。竞态条件可能破坏状态,而基准测试速度更快。
审查共享变量、发布者、客户端、设备句柄和第三方库。使用有界同步,避免在I/O之间保持锁定。通过重复重叠请求和线程净化器或等效测试来强调。
| 组别选择 | 并发 | 有用的 | 主要风险 |
|---|---|---|---|
| 互斥 | 小组里有一次回电 | 有序设备访问 | 隐藏序列化 |
| 重返者 | 重叠回调 | 独立无国籍工作 | 数据种族 |
| 独立的排他性群体 | 跨群的平行 | 独立串行设备 | 跨组共享锁 |
| 专用执行器(Executor) | 独立线程池 | 关键路径隔离 | 协调开销 |
| 非ROS工作人员 | 显式切换 | 分组或批量工作 | 队列所有权 |
避免同步自死锁
发出同步服务请求的回调可能会等待必须在同一互斥组内运行的响应回调。等待的回调保留了该组的资格,因此响应无法执行。类似的循环也会发生在Future对象和Action之间。
倾向于在回调中采用异步流,将依赖回调放入兼容的组中,或使用精心设计的独立执行程序。绘制等待图并测试超时。添加线程不会打破组级排除循环。
执行和等待分布的大小
每次回调,记录调用率、执行时间百分位、最大观测时间和准备等待。尽可能添加CPU亲和力、线程身份和锁等待。线程池大小应根据并发度和阻塞行为确定,而非仅根据处理器核心数数来计算。
包含串行化、中间件获取、内存分配、日志和缓存效果。运行足够长以暴露热限流和后台作业。高吞吐量结果可能与不可接受的控制尾延迟共存。
优先级不是自动的
仅仅选择执行者并不保证操作系统线程优先级、回调优先级或有界抢占。关键回调和尽力回调可以共享工作线程或锁。根据执行者的行为,准备就绪的低重要性回调可能会在控制定时器之前运行。
在截止日期重要时,隔离关键工作,有意识地配置调度和亲和力,移除阻塞操作,并在最坏情况下争用时进行测量。 ROS 2 实时演示 描述的是支持实践,而非任意应用的认证。
将 QoS 延迟与执行器(Executor)延迟区分开
QoS 影响兼容性、保留和传输行为。执行程序影响已准备好回调的运行时间。两者都可能增加采样年龄。将可靠改为尽力可能减少网络积压,但无法修复被互斥单元阻塞的回调。
将源时间戳和序列号带入回调。记录接收准备情况、回调开始和消耗时间。这样可以定位中间件交付前后延迟,防止调错层。
用trace和受控负载诊断
跟踪回调准备、开始和结束事件、执行线程、组身份及相关锁。一次添加一个负载源:高速传感器、服务突发、慢I/O、 CPU负载和网络丢失。在更改设计前保留失败的跟踪。
然后移动或拆分一个回调组,替换一个同步依赖,或卸载一个阻塞任务。重复同样的工作负载。自适应测量比一次性改变多个时序层的完全重写提供了更有力的证据。
将实时路径与便利工作隔离开来
可视化、参数服务、诊断、袋记录和模型推断如果共享执行线程、锁或内存,可能会干扰控制。跨入专用控制线程或执行者时,使用有界队列和明确所有权。
隔离并不能消除通信延迟。定义最新的有效状态,在每个边界处丢弃策略和看门狗。验证尽力而为的工作无法填满被关键路径占用的队列。
按截止日期和数据年龄接受
统计吞吐量,但接受度基于回调等待、执行尾部、错过的定时器周期、样本在使用时的数据年龄和过载恢复。软件和硬件更换后测试同一个回调图。
发布包含组、线程池、调度、共享锁和最坏情况工作负载的执行者合同。
评估“ROS 2执行程序(Executor)与回调组:机器人时序指南”时,还应保存模型版本、机器人配置、标定文件、测试日期和全部试验记录。把成功、失败、恢复与人工介入放在同一份数据中,才能区分模型能力、系统接口和现场流程造成的差异。
成本评估除了设备与算力,还要记录数据采集、工程调试、安全措施、维护、停机和人员培训。只有把这些持续投入与单位成功任务的价值比较,才能判断方案是否适合扩大。
上线后仍要持续检查分布变化、传感器漂移、机械磨损和人工接管原因。监测结果应能触发降级、停止与重新验证流程,并为下一轮数据采集和模型更新留下可追溯记录。
最终结论应明确写出已知限制、尚未验证的场景和下一项可证伪的实验,使后续团队能够沿着证据继续推进。
实际项目还应指定数据、模型、控制器和安全流程的负责人,并预先定义回滚条件。责任边界、审批记录与变更日志越清楚,故障发生后越容易停止扩散、定位原因并安全恢复。
- 清点每个回调及其隐藏依赖。
- 跟踪等待和执行时间分别计算。
- 地图回拨组和共享资源。
- 注入CPU、 I/O、服务和传感器负载。
- 按截止日期和数据新鲜度接受。
常见问题
多线程执行器会并行运行每个回调吗?
不是。调用组规则、现成工作、线程计数和共享锁决定了实际并发。
每次回拨都能留在默认组里吗?
它可以,但默认的互斥群可能会序列化工作,从而破坏预期的并行性。
Reentrant组总是更快吗?
不允许。它只允许重叠;争用、竞赛和额外同步会降低性能或正确性。
Best Effort QoS 修复执行器(Executor)延迟问题吗?
当延迟来自回调调度、锁定或阻塞代码时,就不行了。测量两层。
首先应该测量什么?
每次回调时,测量源数据年龄、准备开始等待、执行时长、线程和回调组。
执行程序时序证据边界
执行器时序取决于ROS分布、 RMW、操作系统、硬件、回调代码和工作负载。测量部署的图;仅靠执行器配置并不能保证实时。