trie, core: use unsafe pool internally in stacktrie
This commit is contained in:
parent
f52e3b7dff
commit
82269e4c91
|
@ -94,11 +94,13 @@ func BenchmarkDeriveSha200(b *testing.B) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
st := trie.NewStackTrie(nil)
|
||||||
b.Run("stack_trie", func(b *testing.B) {
|
b.Run("stack_trie", func(b *testing.B) {
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
have = types.DeriveSha(txs, trie.NewStackTrie(nil))
|
st.Reset()
|
||||||
|
have = types.DeriveSha(txs, st)
|
||||||
}
|
}
|
||||||
if have != want {
|
if have != want {
|
||||||
b.Errorf("have %x want %x", have, want)
|
b.Errorf("have %x want %x", have, want)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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 (
|
var (
|
||||||
|
emptyInit sync.Once
|
||||||
|
emptyBlob *kzg4844.Blob
|
||||||
|
emptyBlobCommit kzg4844.Commitment
|
||||||
|
emptyBlobProof kzg4844.Proof
|
||||||
|
)
|
||||||
|
|
||||||
|
func initEmpties() {
|
||||||
|
emptyInit.Do(func() {
|
||||||
emptyBlob = new(kzg4844.Blob)
|
emptyBlob = new(kzg4844.Blob)
|
||||||
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
|
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
|
||||||
emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
|
emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
|
||||||
)
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
|
func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
|
||||||
blobtx := createEmptyBlobTxInner(withSidecar)
|
blobtx := createEmptyBlobTxInner(withSidecar)
|
||||||
|
@ -71,6 +82,7 @@ func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
|
func createEmptyBlobTxInner(withSidecar bool) *BlobTx {
|
||||||
|
initEmpties()
|
||||||
sidecar := &BlobTxSidecar{
|
sidecar := &BlobTxSidecar{
|
||||||
Blobs: []kzg4844.Blob{*emptyBlob},
|
Blobs: []kzg4844.Blob{*emptyBlob},
|
||||||
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
Commitments: []kzg4844.Commitment{emptyBlobCommit},
|
||||||
|
|
|
@ -53,3 +53,40 @@ func (bp *bytesPool) Put(b []byte) {
|
||||||
default:
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ type StackTrie struct {
|
||||||
onTrieNode OnTrieNode
|
onTrieNode OnTrieNode
|
||||||
kBuf []byte // buf space used for hex-key during insertions
|
kBuf []byte // buf space used for hex-key during insertions
|
||||||
pBuf []byte // buf space used for path 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
|
// NewStackTrie allocates and initializes an empty trie. The committed nodes
|
||||||
|
@ -62,7 +62,7 @@ func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
|
||||||
onTrieNode: onTrieNode,
|
onTrieNode: onTrieNode,
|
||||||
kBuf: make([]byte, 0, 64),
|
kBuf: make([]byte, 0, 64),
|
||||||
pBuf: make([]byte, 0, 32),
|
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() {
|
func (t *StackTrie) Reset() {
|
||||||
t.root = stPool.Get().(*stNode)
|
t.root = stPool.Get().(*stNode)
|
||||||
t.last = nil
|
t.last = nil
|
||||||
|
t.onTrieNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrieKey returns the internal key representation for the given user key.
|
// TrieKey returns the internal key representation for the given user key.
|
||||||
|
|
Loading…
Reference in New Issue