Skip to content

feat(cdr): direct CDR serialization with bulk-copy path for plain sequences - #125

Merged
YuanYuYuan merged 9 commits into
mainfrom
dev/serdes-study
Mar 8, 2026
Merged

feat(cdr): direct CDR serialization with bulk-copy path for plain sequences#125
YuanYuYuan merged 9 commits into
mainfrom
dev/serdes-study

Conversation

@YuanYuYuan

@YuanYuYuan YuanYuYuan commented Mar 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replace the serde-based CDR serialization path with direct trait dispatch for generated message types, eliminating serde reflection overhead. Plain struct sequences (e.g. Vec<Pose>, Vec<f32>) now use bulk memcpy instead of element-by-element serialization. This PR is inspired by ros2/rosidl_typesupport_fastrtps#142.

Key Changes

  • New CDR traits (CdrSerialize, CdrDeserialize, CdrSerializedSize) in ros-z-cdr for direct CDR serialization without serde
  • Bulk-copy path for bytemuck::Pod sequences — Vec<f32>, Vec<Pose>, etc. serialize/deserialize as a single memcpy
  • Codegen emits bytemuck::Pod/Zeroable derives on plain structs and CDR trait impls for all generated message types
  • NativeCdrSerdes<T> blanket wires generated types to the fast path automatically; serde-only types fall back to SerdeCdrSerdes<T>
  • CDR impls for framework types — action message structs and type-description wire types now use the fast path instead of serde
  • ZBuf::cdr_serialize bug fix — was writing the sequence length prefix twice
  • Renamed FastCdrSerdesNativeCdrSerdes and CdrSerdesSerdeCdrSerdes to clarify the two paths

Benchmark results (release build, x86_64)

Workload Serde path Native path Speedup
PoseArray[1000] serialize 5589 ns 3991 ns 1.4×
PoseArray[1000] deserialize 11527 ns 4470 ns 2.6×
Vec<f32>[1000] serialize 992 ns 76 ns 13×
Vec<f32>[1000] deserialize 1105 ns 71 ns 15.5×
Vec<f32>[10000] serialize 8535 ns 764 ns 11×
Vec<f32>[10000] deserialize 9294 ns 694 ns 13.4×

Wire format is byte-identical between the two paths (verified by test).

Breaking Changes

CdrSerdes and FastCdrSerdes are renamed to SerdeCdrSerdes and NativeCdrSerdes. Any code referencing these types by name will need updating.

…ith bytemuck bulk-copy path

Adds direct CDR serialization traits to ros-z-cdr, bypassing serde reflection:
- CdrSerialize / CdrDeserialize / CdrSerializedSize traits in traits.rs
- Bulk-copy path for bytemuck::Pod types (Vec<f32>, Vec<Pose>, etc.)
- Codegen emits bytemuck Pod/Zeroable derives on plain structs and CDR
  trait impls for all generated message types
- CdrSerializedSize enables pre-allocation without serializing
…internal types

- Add NativeCdrSerdes<T> as default ZMessage::Serdes for CDR-capable types via blanket impl
- Implement CdrSerialize/CdrDeserialize/CdrSerializedSize for all concrete
  action message types and type-description wire types (ZBuf, GoalId,
  GoalStatus, GoalInfo, Time, and 11 framework message structs)
- Update Publisher/Subscriber builders to use T::Serdes instead of
  hardcoded SerdeCdrSerdes, preserving serde path for serde-only types
- Fix ZBuf::cdr_serialize double-length-prefix bug
- Rename FastCdrSerdes->NativeCdrSerdes and CdrSerdes->SerdeCdrSerdes
  to clarify which path goes through serde reflection vs direct trait dispatch
…ead_pod_slice

cast_slice requires the input slice to be memory-aligned to align_of::<T>().
Network buffers arriving from ROS2 are not guaranteed to be 8-byte aligned,
causing bytemuck to panic when deserializing f64 arrays (e.g. Imu/Odometry
covariance arrays). Switch to pod_collect_to_vec which handles misalignment
by copying into a fresh aligned allocation.

Also restore the SplitBuffer import in mod tests which was mistakenly removed
(contiguous() is a method on the SplitBuffer trait, used in that module).
@YuanYuYuan
YuanYuYuan merged commit e9a8fcf into main Mar 8, 2026
16 checks passed
@YuanYuYuan
YuanYuYuan deleted the dev/serdes-study branch March 8, 2026 10:36
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.

1 participant