Skip to content

ROS 2 services are not 1 to 1 communication: responses are copied and sent to all clients #2397

Description

@mauropasse

Issue report

Currently if there are 2 (or more) clients with the same /service_name, both will get the server response (one will silently discard it after noticing it wasn't for him).

This has CPU & memory performances implications - in many cases server responses can be quite big - thus unnecessary copies and de-serialization of responses happen, while there could be multiple clients with same name (not uncommon situation).

I verified this problem with rmw_cyclonedds & rmw_fastrtps , on current rolling, humble & galactic.

  // Example
  auto service = node1->create_service<SetBool>("srv_name");
  auto client_1 = node2->create_client<SetBool>("srv_name");
  auto client_2 = node3->create_client<SetBool>("srv_name");

  client_1->async_send_request(...);
  
  // Spin service, so it will get the request and produce a response.
  // The response is received in both clients - one will silently discard it

A full example can be found here, where I'm also using a service message with an 8MB request / 8MB response to better appreciate the performance consequences.

With the mentioned example using the mentioned service, I can compute a CPU FlameGraph showing the difference between having a single client vs having 2 clients with same /service_name, where we can see the extra CPU time overhead:

CPU_FlameGraph_srv_cli_double_delivery

In a one-to-one client-server communication model, a client sends a request to the server, and the server should respond to that specific client.

It'd be nice to find a way to comply with this model. Maybe the Service can store the Client's endpoint, and repond only to it.

Note that this issue doesn't happen if we use intra-process communication between clients & services, where the service only responds to the client who made the request.

The issue was noticed thanks to a log I added in the past, which would be nice to include in rolling:

[ERROR] [1699640383.717414288] [rclcpp]: Error in take_type_erased_response: RCL_RET_CLIENT_TAKE_FAILED. Service name: /persistent_params/list_parameters

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions