Hi,
starting this topic to spread some awareness around the current status of ROS 2 executors in the rclcpp
C++ client library and to discuss their future.
Let’s have a quick look at the available executor classes.
First we have probably the two most famous executors:
- The
SingleThreadedExecutor
: this is the default executor for ROS 2 (and the first developed). It uses wait-sets and processes events in an arbitrary order. - The
MultiThreadedExecutor
: this is a multi-threaded version of theSingleThreadedExecutor
.
The initial implementation of these executors had major performance issues.
So the ROS community spent a good amount of time trying to improve them.
This resulted in a lot of different executors, both open and closed source.
I suggest you to look at the ROSCon 2021 “Executors Workshop”.
Out of all this work, two new executors got into rclcpp
:
- The
StaticSingleThreadedExecutor
: this executor was developed by Nobleo and then improved by iRobot. Its initial implementation was focused on the idea that ROS 2 systems are static at steady-state, so you don’t need to rebuild the list of entities at every iteration. Despite the name, this executor is fully usable also for non-static systems. - The
EventsExecutor
: this executor was developed by iRobot. Its main difference with respect to all the other executors is that it doesn’t use the concept of wait-set, but rather it is based on an events-queue. This results in not paying overhead for entities that are not receiving events and in the possibility of processing events in the correct arrival order.
It uses the same concept as the static executor to avoid rebuilding the list of entities.
As part of ROS 2 Jazzy, the rclcpp maintainers did a major rework of the executors, essentially generalizing the concept used for not having to rebuild the list of entities to all executors (that before was used only by the StaticSingleThreadedExecutor
and the EventsExecutor
).
Let’s have a look at the performance of the executors today, using ROS 2 Rolling and the irobot performance framework.
I created a pseudo-random system with ~40 publishers and ~70 subscriptions spread across 8 executors, let them publish for 60 seconds and I got these numbers (which align with my expectations and previous results):
The conclusions I would like to draw out of this are:
- The
SingleThreadedExecutor
is now more performant than theStaticSingleThreadedExecutor
- The
StaticSingleThreadedExecutor
should now be deprecated: all its improvements are now available in all the other executors; moreover there are open issues and concerns that are specific to its implementation. - The
EventsExecutor
should already be the choice if you are looking for improved performance and we should start the process to promote it as default executor.