While working on this feature, I noticed that pub/sub message delivery time increases roughly in proportion to the buffer size, even though the payload size is expected to remain constant when using specialized buffer backends.
I looked into it a bit and found that std::vector<uint8_t>(buffer_size) zero-initializes the entire buffer, effectively calling memset for buffer_size bytes. Since the buffer does not need to be initialized in this context, I submitted a patch to avoid both the extra memory allocation and the zero-initialization.
rolling ← dskkato:dskkato/reduce_extra_heap_allocations
オープン 08:24AM - 11 Aug 26 UTC
## Description
Previously, heap allocation happend for each endpoint with std… ::vector<uint8_t>. This introduced extra memset via its constructor.
For recent ROS 2, where rosidl::Buffer was introduced, sometimes the actual payload size and message size may not match because only buffer descriptors may be sent. In such a case, now `get_serialized_size()` seems to be unreliable, and hard to pre-allocate the buffer in that path.
Fixes #903
### Is this user-facing behavior change?
Possibly yes.
Previously, it is guaranteed that the heap allocation only happens once per endpoint, through externally managed buffer (allocated with `std::vector<uint8_t>`). Now the number of allocations depends on combinations of buffer's strategies, and Cdr's usage. So, in small message cases, this patch will introduce an extra overhead of buffer reallocation.
For rosidl::Buffer usage, this patch will dramatically reduce extra allocation and zero-initialization when only the optimized message paths exist.
### Did you use Generative AI?
I used CodeX to investigate the cause analysis, and FastBuffer/Cdr behavior.
### Additional Information
This patch is trying to resolve two issues at same time:
1. Reducing extra memory allocation when publishing rosidl::Buffer via optimized buf (carries only a descriptor)
2. Removing extra memset caused by `std::vector<uint8_t>` constructor.
What I originally found is the second point, so if we wish more conservative way, it is possible to reserve the `fast_buffer` as previouslly. Still, I believe it is better to reuse that buffer accross endpoints, in my perspective...
Since this is my first PR to `rmw_fastrtps` repository, let me know if I missed anything.