mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-17 12:21:38 +00:00
trie/bintrie: revert sha256 helper + parallelHashDepth constant
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.
This commit is contained in:
parent
2d44d8a4b6
commit
3885e539b7
2 changed files with 22 additions and 16 deletions
|
|
@ -37,11 +37,3 @@ func newSha256() hash.Hash {
|
||||||
func returnSha256(h hash.Hash) {
|
func returnSha256(h hash.Hash) {
|
||||||
sha256Pool.Put(h)
|
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
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@
|
||||||
package bintrie
|
package bintrie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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.
|
// 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
|
// goroutine while the right subtree is hashed inline, then the two digests
|
||||||
// are combined. Below that threshold the goroutine spawn cost outweighs the
|
// 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 {
|
func (s *NodeStore) hashInternal(idx uint32) common.Hash {
|
||||||
node := s.getInternal(idx)
|
node := s.getInternal(idx)
|
||||||
if !node.mustRecompute {
|
if !node.mustRecompute {
|
||||||
return node.hash
|
return node.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.depth < parallelHashDepth {
|
if int(node.depth) < parallelDepth() {
|
||||||
var input [64]byte
|
var input [64]byte
|
||||||
var lh common.Hash
|
var lh common.Hash
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
@ -75,21 +84,26 @@ func (s *NodeStore) hashInternal(idx uint32) common.Hash {
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
copy(input[:32], lh[:])
|
copy(input[:32], lh[:])
|
||||||
node.hash = sha256Sum256(input[:])
|
node.hash = sha256.Sum256(input[:])
|
||||||
node.mustRecompute = false
|
node.mustRecompute = false
|
||||||
return node.hash
|
return node.hash
|
||||||
}
|
}
|
||||||
|
|
||||||
var input [64]byte
|
h := newSha256()
|
||||||
|
defer returnSha256(h)
|
||||||
if !node.left.IsEmpty() {
|
if !node.left.IsEmpty() {
|
||||||
lh := s.computeHash(node.left)
|
lh := s.computeHash(node.left)
|
||||||
copy(input[:32], lh[:])
|
h.Write(lh[:])
|
||||||
|
} else {
|
||||||
|
h.Write(make([]byte, HashSize))
|
||||||
}
|
}
|
||||||
if !node.right.IsEmpty() {
|
if !node.right.IsEmpty() {
|
||||||
rh := s.computeHash(node.right)
|
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
|
node.mustRecompute = false
|
||||||
return node.hash
|
return node.hash
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue