Has anyone moved a ROS 2 planning pipeline from multi-process nodes to component containers to cut serialization overhead? I’m seeing about 3–5 ms of DDS/copy cost at 200 Hz on Humble (Cyclone DDS), and I’m weighing shared-memory transports and lock-free queues versus keeping isolation before I sink time into kernel-level optimizations — what paid off for you?
I co-located the planner + collision checker in a single rclcpp component container with use_intra_process_comms=true and used rclcpp::LoanedMessage (CycloneDDS + iceoryx); that alone dropped about 3 ms at 200 Hz on Humble… > keeping isolation before I sink time into kernel-level optimizations — what paid off for Co-location + loaned messages beat kernel tweaks for us; small caveat: set history=1 and preallocate SHM chunks to avoid rare stalls. Are you constrained to separate processes for fault isolation?
Quick win for me was pinning the executor and DDS RX threads to the same core and using a single-threaded executor with intra-process; with QoS ‘KEEP_LAST=1/BEST_EFFORT’ that dropped about 2–3 ms at 200 Hz by dodging cross-core wakeups. Before going kernel-deep or rewiring with lock-free queues, run ros2_tracing to confirm it’s copy time and not scheduling jitter: ros-tracing / ros2_tracing · GitLab.
On Humble/Cyclone, the biggest win I saw was to “keep DDS out of the hot path”: inside a component container, replace the planner and collision checker pub/sub with a direct C++ callback using the same allocator, and keep a small debug topic for visibility. That cut those 3–5 ms for me without kernel tweaks, but you give up process isolation — does that fit your constraints or do you need the DDS boundary?
Try passing std::unique_ptr messages inside a component container (use_intra_process_comms=true) so rclcpp does pointer handoff, and pair it with Publisher/SubscriptionOptionsWithAllocator using a monotonic/TLSF allocator to kill alloc churn. If you must keep a DDS hop, stick to POD layouts and enable Cyclone SHM + loaned samples; packing the request and env snapshot into one struct kept the ball in the same court for me. Do those planner↔checker messages include strings or resizable arrays? https://docs.ros.org/en/humble/Concepts/Intermediate/About-Intra-Process-Communication.html.