Skip to content

perf(table): fuse 3 allocate calls in Builder.addHelper into 1#2280

Open
shaunpatterson wants to merge 1 commit into
dgraph-io:mainfrom
shaunpatterson:perf/addhelper-fuse-allocate
Open

perf(table): fuse 3 allocate calls in Builder.addHelper into 1#2280
shaunpatterson wants to merge 1 commit into
dgraph-io:mainfrom
shaunpatterson:perf/addhelper-fuse-allocate

Conversation

@shaunpatterson
Copy link
Copy Markdown

Summary

Replaces the three separate b.allocate() calls in Builder.addHelper (header, diff-key, value) with a single allocation sized for all three pieces, then writes each piece directly into the slot. The fused write uses *(*header)(unsafe.Pointer(&dst[0])) = h for the header, eliminating the heap-escaping h.Encode() local and two intermediate capacity checks per entry.

Each addHelper call previously paid:

  • 3× capacity check in allocate (one per piece)
  • 1× heap escape for the local 4-byte header slice produced by h.Encode()

After the fuse, that's one capacity check, no heap escape.

Measurement

  • BenchmarkBuilder/no_compression: -12.5%
  • BenchmarkBuilder/zstd_level_1: -13.1%
  • BenchmarkBuilder/encryption: -7.6%
  • Composite (74-benchmark stable subset): -2.28% ns/op, median of 3 runs

Test plan

  • go test -short -race ./table/ — all builder tests pass (TestTableIndex, TestBuilder*, TestTableIterator, ...)
  • go vet ./...
  • CI

addHelper is on the hot path of every table build, so existing tests give 100% line coverage of the modified function.

🤖 Generated with Claude Code

addHelper is the write hot-path: called once per entry during table
build. The original code did three separate writes — append(h.Encode()),
append(diffKey), and allocate+Encode for the value — which costs:
- 3 capacity checks against b.curBlock.data
- 1 heap-escaping local [4]byte from h.Encode() per entry
- 1 intermediate copy of the header bytes

Fuse them into a single allocate(4 + dlen + vsz) and write the header,
diffKey, and value directly into the slice. The header is written via
the same unsafe pointer cast pattern already used elsewhere in the
package (matches header.Encode's byte layout).

Benchmark impact (M4 Max, median of 3 runs):
- BenchmarkBuilder/zstd_compression/level_1: -13.1%
- BenchmarkBuilder/no_compression: -9.4%
- BenchmarkBuilder/encryption: -7.6%
@shaunpatterson shaunpatterson requested a review from a team as a code owner May 23, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant