Skip to content

Deserialize subscription payloads in place (backport #1074) - #1085

Open
mergify[bot] wants to merge 1 commit into
lyricalfrom
mergify/bp/lyrical/pr-1074
Open

mergify[bot] wants to merge 1 commit into
lyricalfrom
mergify/bp/lyrical/pr-1074

Conversation

@mergify

@mergify mergify Bot commented Oct 22, 2026

Copy link
Copy Markdown

Description

take_one_message() allocated a buffer of payload_data.size() * 4 + 65536 bytes and copied the payload into it before deserializing. The kilted, jazzy and humble branches already deserialize straight from the payload with FastBuffer, so this brings rolling in line with them and drops the per-message allocation and copy from the subscription hot path.

This is the first option in the issue's suggested handling, and the one the released branches use. Right-sizing by itself is not: as the issue measured, the oversized block is what keeps M_MMAP_THRESHOLD lifted, and with it M_TRIM_THRESHOLD, so removing the oversized block while still allocating costs 30-40% at 1 MiB because glibc returns the heap with brk between messages and the next one re-faults it. Removing the allocation takes the allocator out of the path instead of trading one policy for another.

Payload owns its bytes and msg_data stays alive for the whole deserialization, so the slice stays valid. FastCDR is bounded by the size passed to FastBuffer and raises NotEnoughMemoryException on overrun, so the 4x margin was never addressable by the deserializer.

Related to #1060

Is this user-facing behavior change?

No. Same deserialization result, minus a per-message allocation and copy.

Did you use Generative AI?

Yes, I used an LLM to review the change and to help write this description. The code change is mine.


This is an automatic backport of pull request #1074 done by [Mergify](https://mergify.com).

take_one_message() allocated a buffer sized at four times the payload plus
64 KiB, copied the payload into it, and then built the FastBuffer over
payload_data.size(). The extra capacity was never addressable by the
deserializer: FastCDR is bounded by the size passed to FastBuffer and
raises NotEnoughMemoryException on overrun, so the margin could not be used.

Construct the FastBuffer over the received payload instead, as the released
branches do, and drop the allocation and the full-payload copy. Payload owns
its bytes and msg_data stays alive for the whole deserialization, so the
slice remains valid for as long as the message is processed.

The allocation and the copy were both introduced together in #930. Removing
them restores the behaviour of the released branches while keeping the
endpoint-aware deserialization path that the same commit added.

Signed-off-by: Quchaosheng <quchaosheng000406@163.com>
(cherry picked from commit 678931f)
@ahcorde

ahcorde commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Pulls: #1085
Gist: https://gist.githubusercontent.com/ahcorde/7c829083fef9cc39a28a6fbb2f407cf9/raw/1d2579326001a3143298d3efb8f4e44711339478/ros2.repos
BUILD args: --packages-above-and-dependencies rmw_zenoh_cpp
TEST args: --packages-above rmw_zenoh_cpp
ROS Distro: lyrical
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/20847

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants