From 9cad0a0cc0e5ceba7a05f1927471a4582e171d39 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Wed, 20 Aug 2025 15:11:09 +0800 Subject: [PATCH] all: create global hasher pool #31769 (#1233) This PR creates a global hasher pool that can be used by all packages. It also removes a bunch of the package local pools. It also updates a few locations to use available hashers or the global hashing pool to reduce allocations all over the codebase. This change should reduce global allocation count by ~1% --------- Co-authored-by: Marius van der Wijden Co-authored-by: Gary Rong --- core/types/hashing.go | 3 +-- core/vm/instructions.go | 7 +------ core/vm/interpreter.go | 2 +- crypto/crypto.go | 15 +++++++++++++-- trie/hasher.go | 2 +- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/core/types/hashing.go b/core/types/hashing.go index b30fd44841..76f7069191 100644 --- a/core/types/hashing.go +++ b/core/types/hashing.go @@ -23,12 +23,11 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/rlp" - "golang.org/x/crypto/sha3" ) // hasherPool holds LegacyKeccak256 hashers for rlpHash. var hasherPool = sync.Pool{ - New: func() interface{} { return sha3.NewLegacyKeccak256() }, + New: func() interface{} { return crypto.NewKeccakState() }, } // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 21a7ea3953..e29513a7fa 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -21,7 +21,6 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core/types" - "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/params" "github.com/holiman/uint256" ) @@ -237,11 +236,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( offset, size := scope.Stack.pop(), scope.Stack.peek() data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) - if interpreter.hasher == nil { - interpreter.hasher = crypto.NewKeccakState() - } else { - interpreter.hasher.Reset() - } + interpreter.hasher.Reset() interpreter.hasher.Write(data) interpreter.hasher.Read(interpreter.hasherBuf[:]) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index d7c21adc2d..5bba09ab8c 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -97,7 +97,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { } } evm.Config.ExtraEips = extraEips - return &EVMInterpreter{evm: evm, table: table} + return &EVMInterpreter{evm: evm, table: table, hasher: crypto.NewKeccakState()} } // Run loops and evaluates the contract's code with the given input data and returns diff --git a/crypto/crypto.go b/crypto/crypto.go index d25b286cdc..c68b69ee7c 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -28,6 +28,7 @@ import ( "io" "math/big" "os" + "sync" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/math" @@ -73,6 +74,12 @@ func NewKeccakState() KeccakState { return sha3.NewLegacyKeccak256().(KeccakState) } +var hasherPool = sync.Pool{ + New: func() any { + return sha3.NewLegacyKeccak256().(KeccakState) + }, +} + // HashData hashes the provided data using the KeccakState and returns a 32 byte hash func HashData(kh KeccakState, data []byte) (h common.Hash) { kh.Reset() @@ -84,22 +91,26 @@ func HashData(kh KeccakState, data []byte) (h common.Hash) { // Keccak256 calculates and returns the Keccak256 hash of the input data. func Keccak256(data ...[]byte) []byte { b := make([]byte, 32) - d := NewKeccakState() + d := hasherPool.Get().(KeccakState) + d.Reset() for _, b := range data { d.Write(b) } d.Read(b) + hasherPool.Put(d) return b } // Keccak256Hash calculates and returns the Keccak256 hash of the input data, // converting it to an internal Hash data structure. func Keccak256Hash(data ...[]byte) (h common.Hash) { - d := NewKeccakState() + d := hasherPool.Get().(KeccakState) + d.Reset() for _, b := range data { d.Write(b) } d.Read(h[:]) + hasherPool.Put(d) return h } diff --git a/trie/hasher.go b/trie/hasher.go index 6b101637b9..e1b56477e6 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -35,7 +35,7 @@ type hasher struct { // hasherPool holds pureHashers var hasherPool = sync.Pool{ - New: func() interface{} { + New: func() any { return &hasher{ tmp: make([]byte, 0, 550), // cap is as large as a full fullNode. sha: sha3.NewLegacyKeccak256().(crypto.KeccakState),