From 3885e539b7986d161a91110ee1778018ae75e72c Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sat, 18 Apr 2026 18:50:20 +0200 Subject: [PATCH] trie/bintrie: revert sha256 helper + parallelHashDepth constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gballet asked (comment 3099953085) to leave the sha256Sum256 / constant parallelHashDepth optimisation out of this PR: it's an orthogonal microbenchmark concern that should be revisited post-group-depth under Go 1.26. - Delete the sha256Sum256 helper from hasher.go. - Delete the const parallelHashDepth = 4 from hasher.go. - Restore master's dynamic parallelDepth() helper in store_commit.go (copy verbatim — min(bits.Len(NumCPU), 8)). - In hashInternal's shallow-parallel branch, call sha256.Sum256 directly (std-lib, stack-allocated [32]byte; common.Hash is a type alias for [32]byte so no conversion needed). - In hashInternal's deep-sequential branch, use the pooled newSha256 / returnSha256 hasher (matches master's internal_node.go:170-185). Intentional trade-off: the deep branch now re-introduces per-hash sync.Pool Get/Put plus a 32-byte h.Sum(nil) allocation. Zero regression vs master; foregoes the arena's proposed stack-based hashing until Go 1.26 + post-group-depth benchmarks. --- trie/bintrie/hasher.go | 8 -------- trie/bintrie/store_commit.go | 30 ++++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/trie/bintrie/hasher.go b/trie/bintrie/hasher.go index 74d958028d..b81c145723 100644 --- a/trie/bintrie/hasher.go +++ b/trie/bintrie/hasher.go @@ -37,11 +37,3 @@ func newSha256() hash.Hash { func returnSha256(h hash.Hash) { sha256Pool.Put(h) } - -// sha256Sum256 computes a sha256 digest and returns it as a common.Hash. -func sha256Sum256(data []byte) [32]byte { - return sha256.Sum256(data) -} - -// parallelHashDepth controls the tree hashing parallelization depth threshold -const parallelHashDepth = 4 diff --git a/trie/bintrie/store_commit.go b/trie/bintrie/store_commit.go index e294b1052e..bd94a2383d 100644 --- a/trie/bintrie/store_commit.go +++ b/trie/bintrie/store_commit.go @@ -17,9 +17,11 @@ package bintrie import ( + "crypto/sha256" "errors" "fmt" "math/bits" + "runtime" "sync" "github.com/ethereum/go-ethereum/common" @@ -46,19 +48,26 @@ func (s *NodeStore) computeHash(ref nodeRef) common.Hash { } } +// parallelDepth returns the tree depth below which hashInternal spawns +// goroutines for shallow-depth parallelism. +func parallelDepth() int { + return min(bits.Len(uint(runtime.NumCPU())), 8) +} + // hashInternal hashes an InternalNode and caches the result. // -// At shallow depths (< parallelHashDepth) the left subtree is hashed in a +// At shallow depths (< parallelDepth()) the left subtree is hashed in a // goroutine while the right subtree is hashed inline, then the two digests // are combined. Below that threshold the goroutine spawn cost outweighs the -// hashing work, so deeper nodes hash both children sequentially. +// hashing work, so deeper nodes hash both children sequentially via the +// pooled hasher. func (s *NodeStore) hashInternal(idx uint32) common.Hash { node := s.getInternal(idx) if !node.mustRecompute { return node.hash } - if node.depth < parallelHashDepth { + if int(node.depth) < parallelDepth() { var input [64]byte var lh common.Hash var wg sync.WaitGroup @@ -75,21 +84,26 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash { } wg.Wait() copy(input[:32], lh[:]) - node.hash = sha256Sum256(input[:]) + node.hash = sha256.Sum256(input[:]) node.mustRecompute = false return node.hash } - var input [64]byte + h := newSha256() + defer returnSha256(h) if !node.left.IsEmpty() { lh := s.computeHash(node.left) - copy(input[:32], lh[:]) + h.Write(lh[:]) + } else { + h.Write(make([]byte, HashSize)) } if !node.right.IsEmpty() { rh := s.computeHash(node.right) - copy(input[32:], rh[:]) + h.Write(rh[:]) + } else { + h.Write(make([]byte, HashSize)) } - node.hash = sha256Sum256(input[:]) + node.hash = common.BytesToHash(h.Sum(nil)) node.mustRecompute = false return node.hash }