trie, core: use unsafe pool internally in stacktrie

This commit is contained in:
Martin Holst Swende 2024-11-13 08:59:56 +01:00
parent f52e3b7dff
commit 82269e4c91
No known key found for this signature in database
GPG Key ID: 683B438C05A5DDF0
4 changed files with 58 additions and 6 deletions

View File

@ -94,11 +94,13 @@ func BenchmarkDeriveSha200(b *testing.B) {
}
})
st := trie.NewStackTrie(nil)
b.Run("stack_trie", func(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
have = types.DeriveSha(txs, trie.NewStackTrie(nil))
st.Reset()
have = types.DeriveSha(txs, st)
}
if have != want {
b.Errorf("have %x want %x", have, want)

View File

@ -2,6 +2,7 @@ package types
import (
"crypto/ecdsa"
"sync"
"testing"
"github.com/ethereum/go-ethereum/common"
@ -58,11 +59,21 @@ func TestBlobTxSize(t *testing.T) {
}
}
// emptyInit ensures that we init the kzg empties only once
var (
emptyInit sync.Once
emptyBlob *kzg4844.Blob
emptyBlobCommit kzg4844.Commitment
emptyBlobProof kzg4844.Proof
)
func initEmpties() {
emptyInit.Do(func() {
emptyBlob = new(kzg4844.Blob)
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
)
})
}
func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
blobtx := createEmptyBlobTxInner(withSidecar)
@ -71,6 +82,7 @@ func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
}
func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
initEmpties()
sidecar := &BlobTxSidecar{
Blobs: []kzg4844.Blob{*emptyBlob},
Commitments: []kzg4844.Commitment{emptyBlobCommit},

View File

@ -53,3 +53,40 @@ func (bp *bytesPool) Put(b []byte) {
default:
}
}
// unsafeBytesPool is a pool for byteslices. It is not safe for concurrent use.
type unsafeBytesPool struct {
items [][]byte
w int
}
// newUnsafeBytesPool creates a new bytesPool. The sliceCap sets the capacity of
// newly allocated slices, and the nitems determines how many items the pool
// will hold, at maximum.
func newUnsafeBytesPool(sliceCap, nitems int) *unsafeBytesPool {
return &unsafeBytesPool{
items: make([][]byte, 0, nitems),
w: sliceCap,
}
}
// Get returns a slice.
func (bp *unsafeBytesPool) Get() []byte {
if len(bp.items) > 0 {
last := bp.items[len(bp.items)-1]
bp.items = bp.items[:len(bp.items)-1]
return last
}
return make([]byte, 0, bp.w)
}
// Put returns a slice to the pool. This method
// will ignore slices that are too small or too large (>3x the cap)
func (bp *unsafeBytesPool) Put(b []byte) {
if c := cap(b); c < bp.w || c > 3*bp.w {
return
}
if len(bp.items) < cap(bp.items) {
bp.items = append(bp.items, b)
}
}

View File

@ -50,7 +50,7 @@ type StackTrie struct {
onTrieNode OnTrieNode
kBuf []byte // buf space used for hex-key during insertions
pBuf []byte // buf space used for path during insertions
vPool *bytesPool
vPool *unsafeBytesPool
}
// NewStackTrie allocates and initializes an empty trie. The committed nodes
@ -62,7 +62,7 @@ func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
onTrieNode: onTrieNode,
kBuf: make([]byte, 0, 64),
pBuf: make([]byte, 0, 32),
vPool: newBytesPool(300, 20),
vPool: newUnsafeBytesPool(300, 20),
}
}
@ -113,6 +113,7 @@ func (t *StackTrie) Update(key, value []byte) error {
func (t *StackTrie) Reset() {
t.root = stPool.Get().(*stNode)
t.last = nil
t.onTrieNode = nil
}
// TrieKey returns the internal key representation for the given user key.