Skip to content

execution/stagedsync: reuse commitment BAL-fold buffer across blocks - #22801

Open
sudeepdino008 wants to merge 4 commits into
mainfrom
sudeepdino008/reuse-commitment-fold-buffer
Open

execution/stagedsync: reuse commitment BAL-fold buffer across blocks#22801
sudeepdino008 wants to merge 4 commits into
mainfrom
sudeepdino008/reuse-commitment-fold-buffer

Conversation

@sudeepdino008

@sudeepdino008 sudeepdino008 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

The commitment calculator's BAL fold (computeRootFromBAL) allocated a fresh Updates buffer via cc.updates.NewEmpty() on every block. In ModeParallel that allocates a new prefix-trie arena each time — a fixed 16,384-node slab (~1–1.5 MB) — then throws it away.

This reuses one buffer and Reset()s it per fold instead.

Why

Profiling a from-genesis sync, commitment.newPrefixArena was the single largest execution-time allocator (~20%) — and almost all of it wasted: a block touches a few hundred of the slab's 16k nodes before the whole slab is discarded.

Correctness

The fold buffer is created, filled, consumed into a root, and never retained past the fold — all on the single committer goroutine — so Reset()-reuse is equivalent to a fresh allocation. Reset() already exists and is used on the non-BAL compute path. Existing committer root-assertion tests and the full execution/commitment suite pass through the reused path.

commitmentCalculator.computeRootFromBAL allocated a fresh Updates via
cc.updates.NewEmpty() every block (and per mid-block step checkpoint). For a
ModeParallel calculator that allocates a fresh parallelUpdate -> prefixTrie ->
prefixArena -> new(prefixSlab) — a [16384]prefixNode backing array (~1-1.5MB) —
then discards it. Profiling a from-genesis glamsterdam-devnet-6 sync showed
commitment.newPrefixArena as the single largest execution-time allocator
(~20%, 2.54GB/30s), driven entirely by this per-block NewEmpty.

Keep one reusable cc.balUpdates and Reset() it each fold instead. Reset clears
the buffer while retaining the arena's first slab (the reuse path already used
on the non-BAL compute path). The buffer is fully consumed within each fold on
the single committer goroutine, so reuse is state-equivalent to NewEmpty.

New TestUpdatesParallelReuseAvoidsFreshAlloc: NewEmpty=7 allocs/op -> Reset=0,
buffer left clean (empty keys, root-only trie). Existing committer
root-assertion tests and the full execution/commitment suite pass through the
reused path.
@sudeepdino008
sudeepdino008 marked this pull request as ready for review July 28, 2026 15:00
Comment thread execution/commitment/prefix_trie_test.go Outdated
@yperbasis
yperbasis requested a review from Copilot July 29, 2026 09:59
@yperbasis yperbasis added the Glamsterdam https://eips.ethereum.org/EIPS/eip-7773 label Jul 29, 2026
@yperbasis yperbasis added this to the 3.7.0 milestone Jul 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes the execution staged-sync commitment calculator by reusing a per-block BAL fold commitment.Updates buffer across blocks, avoiding repeated prefix-trie arena slab allocations during from-genesis sync (especially impactful in ModeParallel).

Changes:

  • Add balUpdates to commitmentCalculator and reuse it via Reset() for computeRootFromBAL instead of allocating a fresh Updates each block.
  • Close the reused balUpdates buffer during calculator shutdown.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/stagedsync/committer.go Outdated
The shared commitment context still references it (post-exec ComputeCommitment
runs after the deferred Stop), so closing it was a use-after-close. GC reclaims
the arena at teardown.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

execution/stagedsync/committer.go:270

  • The Stop() comment is misleading: as long as the SharedDomainsCommitmentContext still references the Updates buffer via SetUpdates, the buffer cannot be GC’d even after the calculator is dropped. It would be clearer to state that we intentionally avoid Close() because the buffer may still be referenced, and it will only become collectible after the commitment context is pointed at a different Updates instance.
	// Not closed here: the shared commitment context may still reference it
	// (post-exec ComputeCommitment); GC reclaims it when the calculator drops.

@sudeepdino008
sudeepdino008 force-pushed the sudeepdino008/reuse-commitment-fold-buffer branch from 2c696cc to 8e34251 Compare July 30, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Glamsterdam https://eips.ethereum.org/EIPS/eip-7773

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants