Add to_segment_views for zero-copy serialization - #405
Merged
Conversation
haata
approved these changes
Jul 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a implementation of #402
Summary
This PR adds a new opt-in zero-copy API for segmented message output:
to_segment_views()returns a sequence of read-only Python buffer exporters that point directly at the Cap'n Proto message builder's output segments. This lets high-throughput callers pass segments to buffer-consuming transports without first copying each segment into a Pythonbytesobject.The existing
to_segments()API is preserved and still returns Python-owned copiedbytesobjects.Motivation
to_segments()currently materializes each Cap'n Proto output segment as Pythonbytes, which is safe and backwards-compatible but forces a copy before the data reaches a transport or IPC layer. Cap'n Proto's segmented layout is naturally suited for scatter-gather and multipart transports, so exposing borrowed read-only segment views gives performance-sensitive users a way to avoid that extra copy.Changes
_SegmentViewsand_SegmentViewCython types._SegmentViewusingPyBuffer_FillInfo(..., readonly=1, ...)._DynamicStructBuilder.to_segment_views()._DynamicStructBuilder.to_segments()behavior unchanged and updates its docstring to clarify that it returns copiedbytes.from_segments(), compatibility withto_segments(), root-only behavior, and lifetime pinning.Compatibility and Lifetime
to_segments()remains the compatibility API:to_segment_views()is explicitly borrowed:The returned segment views keep the underlying message builder alive, including custom allocator-backed builders. Callers must not mutate, reset, or reuse the builder while any returned segment view is still in use, because the views point into the builder's arena.
Testing
Ran with the repository
.venv:Result:
Also manually verified that
memoryview(msg.to_segment_views()[0])is read-only and has byte content matchingmsg.to_segments()[0].Full-suite note: running the full suite with local socket permissions enabled produced
146 passed, 1 xfailed, 1 failed. The remaining failure wastest_bundled_import_hookwhen running from the source checkout, where the localcapnp/source directory does not contain bundled.capnppackage data. The installed.venvpackage does containstream.capnp, andfrom capnp import stream_capnpsucceeds when importing from the installed package path.