Skip to content

Use a single executor instance for spinning in client_async_callback. #382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2024

Conversation

clalancette
Copy link
Contributor

In the current code, it calls rclpy.spin_once(), which instantiates a new executor, adds the node to it, executors one work item, then removes the node and destroys the executor.

Besides being inefficient, the problem with that sequence is that adding a node to the executor actually ends up being an "event", and so the work item that gets returned can be just the work of adding the node, over and over again. For reasons I admit I don't fully understand, this only happens with rmw_cyclonedds_cpp, not with rmw_fastrtps_cpp.

Regardless, the much more performant thing to do is to create an executor at the beginning of the example and to just spin on that. This eliminates adding it to the node constantly, and makes this work with all RMWs.

In the current code, it calls rclpy.spin_once(), which
instantiates a new executor, adds the node to it, executors
one work item, then removes the node and destroys the executor.

Besides being inefficient, the problem with that sequence
is that adding a node to the executor actually ends up
being an "event", and so the work item that gets returned
can be just the work of adding the node, over and over again.
For reasons I admit I don't fully understand, this only happens
with rmw_cyclonedds_cpp, not with rmw_fastrtps_cpp.

Regardless, the much more performant thing to do is to create
an executor at the beginning of the example and to just spin
on that.  This eliminates adding it to the node constantly,
and makes this work with all RMWs.

Signed-off-by: Chris Lalancette <[email protected]>
Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fix lgtm, but i cannot explain why this is happening with cyclonedds either.

it never takes the service response from the server, server has sent the service response to the client for sure. (maybe we would keep this follow-up on rmw_cyclonedds repo. it is easy to reproduce to revert this fix.)

@clalancette
Copy link
Contributor Author

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Windows Build Status

@clalancette
Copy link
Contributor Author

(maybe we would keep this follow-up on rmw_cyclonedds repo. it is easy to reproduce to revert this fix.)

Yeah, good point. I'll open an issue on https://github.com/ros2/rmw_cyclonedds to follow-up with that.

@clalancette
Copy link
Contributor Author

See ros2/rmw_cyclonedds#494

Copy link
Member

@wjwwood wjwwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

I am digging into why this happens only with rmw_cyclonedds. As you pointed out in ros2/rmw_cyclonedds#494 @clalancette, it's due to a single kind of event being processed each time you spin which is never the event you want.

I think this change is just better though. The "global" version of spin_once() is kind of not that useful and in this case harmful, at least in my opinion. We could consider deprecating and then removing it. But the issue with cyclone should still be followed up on.

@wjwwood
Copy link
Member

wjwwood commented May 16, 2024

@ros-pull-request-builder retest this please

@wjwwood
Copy link
Member

wjwwood commented May 16, 2024

@clalancette
Copy link
Contributor Author

I think the Rpr failure is an unrelated (probably pre-existing) failure: https://build.ros2.org/job/Rpr__examples__ubuntu_noble_amd64/19/testReport/launch_testing_examples.launch_testing_examples/record_rosbag_launch_test/launch_testing_examples_record_rosbag_launch_test/

Yeah, agreed. I'm going to go ahead and merge this in, thanks for the reviews!

@clalancette clalancette merged commit 7e47aee into rolling May 16, 2024
2 of 3 checks passed
@delete-merged-branch delete-merged-branch bot deleted the clalancette/fix-client-async-callback branch May 16, 2024 20:36
@clalancette
Copy link
Contributor Author

@Mergifyio backport jazzy

Copy link
Contributor

mergify bot commented May 16, 2024

backport jazzy

✅ Backports have been created

mergify bot pushed a commit that referenced this pull request May 16, 2024
…#382)

In the current code, it calls rclpy.spin_once(), which
instantiates a new executor, adds the node to it, executors
one work item, then removes the node and destroys the executor.

Besides being inefficient, the problem with that sequence
is that adding a node to the executor actually ends up
being an "event", and so the work item that gets returned
can be just the work of adding the node, over and over again.
For reasons I admit I don't fully understand, this only happens
with rmw_cyclonedds_cpp, not with rmw_fastrtps_cpp.

Regardless, the much more performant thing to do is to create
an executor at the beginning of the example and to just spin
on that.  This eliminates adding it to the node constantly,
and makes this work with all RMWs.

Signed-off-by: Chris Lalancette <[email protected]>
(cherry picked from commit 7e47aee)

# Conflicts:
#	rclpy/services/minimal_client/examples_rclpy_minimal_client/client_async_callback.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants