Skip to content

Optimize MemorySegment.copy calls by avoiding wrapper allocation#2027

Merged
jfallows merged 3 commits into
developfrom
claude/simd-jsontokenizer-profiling-2-ad1tnr
Jul 5, 2026
Merged

Optimize MemorySegment.copy calls by avoiding wrapper allocation#2027
jfallows merged 3 commits into
developfrom
claude/simd-jsontokenizer-profiling-2-ad1tnr

Conversation

@jfallows

@jfallows jfallows commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Description

Optimize getBytes() methods in UnsafeBufferEx by using the direct array overload of MemorySegment.copy() instead of wrapping the destination array in a MemorySegment.ofArray() wrapper.

Changes

  • Updated 4 getBytes() call sites (2 in the outer class, 2 in an inner class) to pass the byte array directly to MemorySegment.copy() instead of wrapping it first
  • Removed unnecessary MemorySegment.ofArray(dst) wrapper construction and corresponding BYTE_LAYOUT parameter
  • Added explanatory comments documenting the performance rationale

Motivation

Profiling identified that per-call MemorySegment.ofArray() wrapper construction was a dominant cost for this method when processing small documents with many verbatim key/value deliveries. The wrapper creates a fresh heap-session-scoped MemorySegment with no cacheable form for arbitrary caller-supplied arrays, making it wasteful for frequent small operations.

The direct array overload of MemorySegment.copy() copies directly into the destination array without constructing an intermediate wrapper, eliminating this allocation overhead.

Test Plan

Existing tests cover these code paths. No new tests required for this optimization.

https://claude.ai/code/session_01FdmT7MqTozanMnH2rLiE8F

claude added 3 commits July 5, 2026 22:00
…nsafeBufferEx.getBytes()

MemorySegment.copy(segment, layout, srcOffset, dst, offset, length) copies
directly into a plain byte[] array, so per-call construction of a fresh
MemorySegment.ofArray(dst) wrapper is unnecessary. Applied to
getBytes(int, byte[], int, int), the dstArray branch of
getBytes(int, MutableDirectBuffer, int, int), and the equivalent methods on
the nested Native variant.

Profiling a downstream JSON tokenizer (zilla-plus) found this per-call
allocation dominant for small documents with many verbatim key/value
deliveries through WindowBuffer.getBytes().

@jfallows jfallows left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jfallows jfallows merged commit 0bfe493 into develop Jul 5, 2026
3 checks passed
@jfallows jfallows deleted the claude/simd-jsontokenizer-profiling-2-ad1tnr branch July 5, 2026 22:43
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