mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/state/snapshot: retain cumulative across states
This commit is contained in:
parent
59009896b9
commit
26876ee39a
4 changed files with 42 additions and 23 deletions
|
|
@ -231,32 +231,38 @@ func (dl *diffLayer) initBloom() {
|
|||
// bloom
|
||||
func (dl *diffLayer) Prepare(origin *diskLayer) {
|
||||
dl.lock.Lock()
|
||||
defer dl.lock.Unlock()
|
||||
// If we already have a cumulative bloom, we're done here
|
||||
if dl.cumulative != nil {
|
||||
return
|
||||
}
|
||||
// Traverse up the parent tree
|
||||
dl.cumulative, _ = dl.diffed.Copy()
|
||||
layer := dl
|
||||
for {
|
||||
if parent, ok := layer.parent.(*diffLayer); ok {
|
||||
parent.lock.RLock()
|
||||
dl.cumulative.UnionInPlace(parent.diffed)
|
||||
parent.lock.RUnlock()
|
||||
layer = parent
|
||||
} else {
|
||||
parent, ok := layer.parent.(*diffLayer)
|
||||
if !ok {
|
||||
break // We hit the disk layer
|
||||
}
|
||||
parent.lock.Lock()
|
||||
// If we're lucky, the parent has a cumulative we can use.
|
||||
if parent.cumulative != nil {
|
||||
// Copy, nuke and done.
|
||||
dl.cumulative.UnionInPlace(parent.cumulative)
|
||||
parent.cumulative = nil
|
||||
parent.lock.Unlock()
|
||||
break
|
||||
}
|
||||
dl.cumulative.UnionInPlace(parent.diffed)
|
||||
parent.lock.Unlock()
|
||||
layer = parent
|
||||
}
|
||||
dl.origin = origin
|
||||
dl.lock.Unlock()
|
||||
// Calculate the current false positive rate and update the error rate meter.
|
||||
k := float64(dl.cumulative.K())
|
||||
n := float64(dl.cumulative.N())
|
||||
m := float64(dl.cumulative.M())
|
||||
snapshotBloomErrorGauge.Update(math.Pow(1.0-math.Exp((-k)*(n+0.5)/(m-1)), k))
|
||||
|
||||
}
|
||||
|
||||
func (dl *diffLayer) Release() {
|
||||
dl.lock.Lock()
|
||||
dl.cumulative = nil
|
||||
dl.lock.Unlock()
|
||||
}
|
||||
|
||||
// Root returns the root hash for which this snapshot was made.
|
||||
|
|
|
|||
|
|
@ -166,4 +166,3 @@ func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]str
|
|||
}
|
||||
|
||||
func (dl *diskLayer) Prepare(*diskLayer) {}
|
||||
func (dl *diskLayer) Release() {}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
|
|
@ -65,8 +66,9 @@ var (
|
|||
snapshotFlushStorageItemMeter = metrics.NewRegisteredMeter("state/snapshot/flush/storage/item", nil)
|
||||
snapshotFlushStorageSizeMeter = metrics.NewRegisteredMeter("state/snapshot/flush/storage/size", nil)
|
||||
|
||||
snapshotBloomIndexTimer = metrics.NewRegisteredResettingTimer("state/snapshot/bloom/index", nil)
|
||||
snapshotBloomErrorGauge = metrics.NewRegisteredGaugeFloat64("state/snapshot/bloom/error", nil)
|
||||
snapshotBloomPrepareTimer = metrics.NewRegisteredResettingTimer("state/snapshot/bloom/prepare", nil)
|
||||
snapshotBloomIndexTimer = metrics.NewRegisteredResettingTimer("state/snapshot/bloom/index", nil)
|
||||
snapshotBloomErrorGauge = metrics.NewRegisteredGaugeFloat64("state/snapshot/bloom/error", nil)
|
||||
|
||||
snapshotBloomAccountTrueHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/account/truehit", nil)
|
||||
snapshotBloomAccountFalseHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/account/falsehit", nil)
|
||||
|
|
@ -107,7 +109,6 @@ type Snapshot interface {
|
|||
// Storage directly retrieves the storage data associated with a particular hash,
|
||||
// within a particular account.
|
||||
Storage(accountHash, storageHash common.Hash) ([]byte, error)
|
||||
Release()
|
||||
}
|
||||
|
||||
// snapshot is the internal version of the snapshot data layer that supports some
|
||||
|
|
@ -219,6 +220,9 @@ func (t *Tree) waitBuild() {
|
|||
}
|
||||
|
||||
func (t *Tree) PrepareSnapshot(blockRoot common.Hash) Snapshot {
|
||||
defer func(start time.Time) {
|
||||
snapshotBloomPrepareTimer.Update(time.Since(start))
|
||||
}(time.Now())
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
if snap := t.layers[blockRoot]; snap != nil {
|
||||
|
|
@ -324,9 +328,6 @@ func (t *Tree) Cap(root common.Hash, layers int) error {
|
|||
default:
|
||||
// Many layers requested to be retained, cap normally
|
||||
persisted = t.cap(diff, layers)
|
||||
if persisted != nil {
|
||||
t.diskLayer = persisted
|
||||
}
|
||||
}
|
||||
// Remove any layer that is stale or links into a stale layer
|
||||
children := make(map[common.Hash][]common.Hash)
|
||||
|
|
@ -349,7 +350,21 @@ func (t *Tree) Cap(root common.Hash, layers int) error {
|
|||
remove(root)
|
||||
}
|
||||
}
|
||||
// If the disk layer was modified, regenerate all the cummulative blooms
|
||||
// If the disk layer was modified, wipe all the cumulative blooms
|
||||
if persisted != nil {
|
||||
// Update ref
|
||||
t.diskLayer = persisted
|
||||
var wipeCumulative func(root common.Hash)
|
||||
wipeCumulative = func(root common.Hash) {
|
||||
if diff, ok := t.layers[root].(*diffLayer); ok {
|
||||
diff.cumulative = nil
|
||||
}
|
||||
for _, child := range children[root] {
|
||||
wipeCumulative(child)
|
||||
}
|
||||
}
|
||||
wipeCumulative(persisted.root)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -866,7 +866,6 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
|||
log.Warn("Failed to cap snapshot tree", "root", root, "layers", 127, "err", err)
|
||||
}
|
||||
}
|
||||
s.snap.Release()
|
||||
s.snap, s.snapDestructs, s.snapAccounts, s.snapStorage = nil, nil, nil, nil
|
||||
}
|
||||
return root, err
|
||||
|
|
|
|||
Loading…
Reference in a new issue