Skip to content

add super.Arena to batch value copies in sbuf.Array#7065

Open
nishantmehta wants to merge 1 commit into
brimdata:mainfrom
nishantmehta:pr/sbuf-arena
Open

add super.Arena to batch value copies in sbuf.Array#7065
nishantmehta wants to merge 1 commit into
brimdata:mainfrom
nishantmehta:pr/sbuf-arena

Conversation

@nishantmehta

Copy link
Copy Markdown

Closes #7064.

Problem

sbuf.Array.Write copies every value with Value.Copybytes.Clone, so it
allocates once per non-native value. Reading a large input into an Array
allocates proportionally to the value count — BenchmarkReadBSUP (10M values)
does ~10M allocations.

Change

Add a chunked super.Arena and have sbuf.Array copy through it:

  • value payloads are appended into 64 KiB chunks;
  • a chunk is never reallocated once it holds a value, so values copied
    earlier remain valid as later ones are appended (when a chunk fills, a fresh
    one is allocated and the old one is kept alive by the values referencing it);
  • native values carry their payload inline and are returned unchanged (no
    allocation), matching Value.Copy;
  • a value with no bytes (including a null) is returned with its bytes
    unchanged, preserving the nil-vs-empty distinction bytes.Clone would;
  • the returned bytes use a 3-index slice so appends can't scribble into the
    arena's spare capacity.

Result

BenchmarkReadBSUP:

before after delta
allocs/op 10,000,416 904 −99.99%
B/op 1.63 Gi 1.59 Gi −2.6%

ns/op is unchanged (the benchmark is GC/bandwidth-bound); the win is the
collapse in allocation count and the resulting GC pressure on large reads.

Testing

  • TestArenaCopy covers native values, source-buffer independence, null
    (nil-bytes) preservation, values spanning many chunks, and a value larger
    than one chunk.
  • go test -short ./... passes across the repo (round-trips unchanged).

sbuf.Array.Write copied every value individually via Value.Copy, which
calls bytes.Clone and allocates once per value. Reading a large input
into an Array therefore allocates once per value: BenchmarkReadBSUP
(10M values) does ~10M allocations.

Add a chunked super.Arena that copies value bytes into 64 KiB chunks.
A chunk is never reallocated once it holds a value, so earlier values
stay valid as later ones are appended. Native values are returned
unchanged (no allocation), and a value with no bytes keeps its
nil-vs-empty distinction. sbuf.Array now copies through an Arena.

BenchmarkReadBSUP: 10,000,416 -> 904 allocs/op (-99.99%), B/op -2.6%.
@nishantmehta nishantmehta marked this pull request as ready for review June 24, 2026 15:00
@nishantmehta nishantmehta marked this pull request as draft June 24, 2026 15:32
@nishantmehta nishantmehta marked this pull request as ready for review June 26, 2026 13:48
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.

sbuf.Array allocates once per value when materializing large inputs

1 participant