triedb/pathdb: remove sync pool

This commit is contained in:
Gary Rong 2025-02-20 10:24:04 +08:00
parent 350a82c582
commit c02137bc6f
2 changed files with 46 additions and 38 deletions

View file

@ -31,8 +31,17 @@ import (
// thread-safe to use. However, callers need to ensure the thread-safety // thread-safe to use. However, callers need to ensure the thread-safety
// of the referenced layer by themselves. // of the referenced layer by themselves.
type layerTree struct { type layerTree struct {
base *diskLayer base *diskLayer
layers map[common.Hash]layer layers map[common.Hash]layer
// descendants is a two-dimensional map where the keys represent
// an ancestor state root, and the values are the state roots of
// all its descendants.
//
// For example: r -> [c1, c2, ..., cn], where c1 through cn are
// the descendants of state r.
//
// This map includes all the existing diff layers and the disk layer.
descendants map[common.Hash]map[common.Hash]struct{} descendants map[common.Hash]map[common.Hash]struct{}
lookup *lookup lookup *lookup
lock sync.RWMutex lock sync.RWMutex
@ -152,8 +161,13 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
tree.lock.Lock() tree.lock.Lock()
defer tree.lock.Unlock() defer tree.lock.Unlock()
// Link the given layer into the layer set
tree.layers[l.rootHash()] = l tree.layers[l.rootHash()] = l
// Link the given layer into its ancestors (up to the current disk layer)
tree.fillAncestors(l) tree.fillAncestors(l)
// Link the given layer into the state mutation history
tree.lookup.addLayer(l) tree.lookup.addLayer(l)
return nil return nil
} }
@ -185,6 +199,8 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
tree.layers = map[common.Hash]layer{ tree.layers = map[common.Hash]layer{
base.rootHash(): base, base.rootHash(): base,
} }
// Resets the descendants map, since there's only a single disk layer
// with no descendants.
tree.descendants = make(map[common.Hash]map[common.Hash]struct{}) tree.descendants = make(map[common.Hash]map[common.Hash]struct{})
tree.lookup = newLookup(base, tree.isDescendant) tree.lookup = newLookup(base, tree.isDescendant)
return nil return nil
@ -227,7 +243,7 @@ func (tree *layerTree) cap(root common.Hash, layers int) error {
// ->C2'->C3'->C4' // ->C2'->C3'->C4'
// //
// After change: // After change:
// Chain: // Chain:
// (a) C3->C4 (HEAD) // (a) C3->C4 (HEAD)
// (b) C1->C2 // (b) C1->C2
// ->C2'->C3'->C4' // ->C2'->C3'->C4'
@ -291,6 +307,7 @@ func (tree *layerTree) bottom() *diskLayer {
// lookupAccount returns the layer that is confirmed to contain the account data // lookupAccount returns the layer that is confirmed to contain the account data
// being searched for. // being searched for.
func (tree *layerTree) lookupAccount(accountHash common.Hash, state common.Hash) (layer, error) { func (tree *layerTree) lookupAccount(accountHash common.Hash, state common.Hash) (layer, error) {
// Hold the read lock to prevent the unexpected layer changes
tree.lock.RLock() tree.lock.RLock()
defer tree.lock.RUnlock() defer tree.lock.RUnlock()
@ -308,6 +325,7 @@ func (tree *layerTree) lookupAccount(accountHash common.Hash, state common.Hash)
// lookupStorage returns the layer that is confirmed to contain the storage slot // lookupStorage returns the layer that is confirmed to contain the storage slot
// data being searched for. // data being searched for.
func (tree *layerTree) lookupStorage(accountHash common.Hash, slotHash common.Hash, state common.Hash) (layer, error) { func (tree *layerTree) lookupStorage(accountHash common.Hash, slotHash common.Hash, state common.Hash) (layer, error) {
// Hold the read lock to prevent the unexpected layer changes
tree.lock.RLock() tree.lock.RLock()
defer tree.lock.RUnlock() defer tree.lock.RUnlock()

View file

@ -25,31 +25,23 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
// slicePool is a shared pool of hash slice, for reducing the GC pressure.
var slicePool = sync.Pool{
New: func() interface{} {
slice := make([]common.Hash, 0, 16) // Pre-allocate a slice with a reasonable capacity.
return &slice
},
}
// getSlice obtains the hash slice from the shared pool.
func getSlice() []common.Hash {
slice := *slicePool.Get().(*[]common.Hash)
slice = slice[:0]
return slice
}
// returnSlice returns the hash slice back to the shared pool for following usage.
func returnSlice(slice []common.Hash) {
slicePool.Put(&slice)
}
// lookup is an internal structure used to efficiently determine the layer in // lookup is an internal structure used to efficiently determine the layer in
// which a state entry resides. // which a state entry resides.
type lookup struct { type lookup struct {
accounts map[common.Hash][]common.Hash // accounts represents the mutation history for specific accounts.
storages map[common.Hash]map[common.Hash][]common.Hash // The key is the account address hash, and the value is a slice
// of **diff layer** IDs indicating where the account was modified,
// with the order from oldest to newest.
accounts map[common.Hash][]common.Hash
// storages represents the mutation history for specific storage
// slot. The key is the account address hash and the storage key
// hash, the value is a slice of **diff layer** IDs indicating
// where the slot was modified, with the order from oldest to newest.
storages map[common.Hash]map[common.Hash][]common.Hash
// descendant is the callback indicating whether the layer with
// given root is a descendant of the one specified by `ancestor`.
descendant func(state common.Hash, ancestor common.Hash) bool descendant func(state common.Hash, ancestor common.Hash) bool
} }
@ -87,9 +79,9 @@ func newLookup(head layer, descendant func(state common.Hash, ancestor common.Ha
// If found, the account data corresponding to the supplied stateID resides // If found, the account data corresponding to the supplied stateID resides
// in that layer. Otherwise, two scenarios are possible: // in that layer. Otherwise, two scenarios are possible:
// //
// The account remains unmodified from the current disk layer up to the state // (a) the account remains unmodified from the current disk layer up to the state
// layer specified by the stateID: fallback to the disk layer for data retrieval. // layer specified by the stateID: fallback to the disk layer for data retrieval,
// Or the layer specified by the stateID is stale: reject the data retrieval. // (b) or the layer specified by the stateID is stale: reject the data retrieval.
func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base common.Hash) common.Hash {
list := l.accounts[accountHash] list := l.accounts[accountHash]
for i := len(list) - 1; i >= 0; i-- { for i := len(list) - 1; i >= 0; i-- {
@ -114,10 +106,10 @@ func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base c
// If found, the storage data corresponding to the supplied stateID resides // If found, the storage data corresponding to the supplied stateID resides
// in that layer. Otherwise, two scenarios are possible: // in that layer. Otherwise, two scenarios are possible:
// //
// The storage slot remains unmodified from the current disk layer up to the // (a) the storage slot remains unmodified from the current disk layer up to
// state layer specified by the stateID: fallback to the disk layer for data // the state layer specified by the stateID: fallback to the disk layer for
// retrieval. Or the layer specified by the stateID is stale: reject the data // data retrieval, (b) or the layer specified by the stateID is stale: reject
// retrieval. // the data retrieval.
func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, stateID common.Hash, base common.Hash) common.Hash {
subset, exists := l.storages[accountHash] subset, exists := l.storages[accountHash]
if exists { if exists {
@ -159,7 +151,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
for accountHash := range diff.states.accountData { for accountHash := range diff.states.accountData {
list, exists := l.accounts[accountHash] list, exists := l.accounts[accountHash]
if !exists { if !exists {
list = getSlice() list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool
} }
list = append(list, state) list = append(list, state)
l.accounts[accountHash] = list l.accounts[accountHash] = list
@ -178,7 +170,7 @@ func (l *lookup) addLayer(diff *diffLayer) {
for slotHash := range slots { for slotHash := range slots {
list, exists := subset[slotHash] list, exists := subset[slotHash]
if !exists { if !exists {
list = getSlice() list = make([]common.Hash, 0, 16) // TODO(rjl493456442) use sync pool
} }
list = append(list, state) list = append(list, state)
subset[slotHash] = list subset[slotHash] = list
@ -212,7 +204,7 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
if i == 0 { if i == 0 {
list = list[1:] list = list[1:]
if cap(list) > 1024 { if cap(list) > 1024 {
list = append(getSlice(), list...) list = append(make([]common.Hash, 0, len(list)), list...)
} }
} else { } else {
list = append(list[:i], list[i+1:]...) list = append(list[:i], list[i+1:]...)
@ -227,7 +219,6 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
if len(list) != 0 { if len(list) != 0 {
l.accounts[accountHash] = list l.accounts[accountHash] = list
} else { } else {
returnSlice(list)
delete(l.accounts, accountHash) delete(l.accounts, accountHash)
} }
} }
@ -252,7 +243,7 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
if i == 0 { if i == 0 {
list = list[1:] list = list[1:]
if cap(list) > 1024 { if cap(list) > 1024 {
list = append(getSlice(), list...) list = append(make([]common.Hash, 0, len(list)), list...)
} }
} else { } else {
list = append(list[:i], list[i+1:]...) list = append(list[:i], list[i+1:]...)
@ -267,7 +258,6 @@ func (l *lookup) removeLayer(diff *diffLayer) error {
if len(list) != 0 { if len(list) != 0 {
subset[slotHash] = list subset[slotHash] = list
} else { } else {
returnSlice(subset[slotHash])
delete(subset, slotHash) delete(subset, slotHash)
} }
} }