Skip to content

docs: ByteBuffer interop + pledged-size zero-copy decode#6

Merged
dfa1 merged 2 commits into
mainfrom
docs/byte-buffer-and-pledged-zero-copy
Jun 26, 2026
Merged

docs: ByteBuffer interop + pledged-size zero-copy decode#6
dfa1 merged 2 commits into
mainfrom
docs/byte-buffer-and-pledged-zero-copy

Conversation

@dfa1

@dfa1 dfa1 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

What

Two zero-copy design clarifications, plus tests for the pledged-size one.

ByteBuffer gap

docs/zero-copy.md now has a ByteBuffer interop section. The segment API already bridges the FFM↔NIO boundary both ways at zero copy — MemorySegment.ofBuffer(buf) in, segment.asByteBuffer() out — so no parallel ByteBuffer overload set is warranted. Documents the two rough edges a proposed toByteBuffer() convenience would smooth: asByteBuffer() returns a BIG_ENDIAN buffer regardless of platform, and the buffer borrows the arena's lifetime.

Pledged size unlocks zero-copy decode

A streamed frame does not record its decompressed size, so decompress(arena, frame) cannot size the output arena and throws — the consumer is forced back onto bounded streaming or a guessed maxSize. ZstdOutputStream.withPledgedSize(...) stamps the content size into the header and unlocks one-shot zero-copy decode. Documented as a correctness gate, not a micro-optimization.

Two new unit tests in ZstdStreamTest$PledgedSize:

  • plainStreamFrameCannotBeSizedForZeroCopyDecodeZstd.decompressedSize throws "not stored"
  • pledgedFrameDecodesZeroCopyIntoArenaInOneShot — arena sized exactly from the header, round-trips

No production code change — withPledgedSize already exists; this documents and tests its importance.

Test

./mvnw -pl zstd -am test -Dtest='ZstdStreamTest$PledgedSize' — 3 green, checkstyle clean.

🤖 Generated with Claude Code

dfa1 and others added 2 commits June 26, 2026 17:39
Document the ByteBuffer gap in the zero-copy design: the segment API
already bridges NIO both ways at zero copy (MemorySegment.ofBuffer in,
asByteBuffer out), so no parallel ByteBuffer overload set is needed. Note
the rough edges that a proposed toByteBuffer() sugar would smooth (byte
order, borrowed arena lifetime).

Explain why pledging the source size is a correctness gate for zero-copy
decode, not a micro-optimization: a streamed frame omits the content size,
so decompress(arena, frame) cannot size the output arena and throws;
withPledgedSize stamps the header and unlocks one-shot zero-copy decode.

Add two unit tests covering the contrast:
- a plain stream frame cannot be sized for zero-copy decode
- a pledged frame decodes zero-copy into an arena in one shot

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
asByteBuffer() on a native segment already returns a direct buffer
aliasing the off-heap bytes; the only wart is byte order. Replace the
nonexistent toByteBuffer() headline with the working one-liner
(asByteBuffer().order(nativeOrder())) and demote the sugar to an
optional wrapper. Align the pledged-size example to level 6.

Rework pledgedFrameDecodesZeroCopyIntoArenaInOneShot to exercise both
zero-copy directions: direct ByteBuffer -> MemorySegment.ofBuffer in,
out.asByteBuffer() hand-off out, instead of the copyIn heap path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dfa1 dfa1 merged commit 8bfe272 into main Jun 26, 2026
1 check passed
@dfa1 dfa1 deleted the docs/byte-buffer-and-pledged-zero-copy branch June 26, 2026 15:46
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