mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie/triedb/pathdb: improve dirty node flushing trigger
This commit is contained in:
parent
4cbca5178a
commit
665597c631
2 changed files with 51 additions and 33 deletions
|
|
@ -172,37 +172,65 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
|
|||
dl.lock.Lock()
|
||||
defer dl.lock.Unlock()
|
||||
|
||||
// Construct and store the state history first. If crash happens
|
||||
// after storing the state history but without flushing the
|
||||
// corresponding states(journal), the stored state history will
|
||||
// be truncated in the next restart.
|
||||
// Construct and store the state history first. If crash happens after storing
|
||||
// the state history but without flushing the corresponding states(journal),
|
||||
// the stored state history will be truncated from head in the next restart.
|
||||
var (
|
||||
overflow bool
|
||||
oldest uint64
|
||||
)
|
||||
if dl.db.freezer != nil {
|
||||
err := writeHistory(dl.db.diskdb, dl.db.freezer, bottom, dl.db.config.StateHistory)
|
||||
err := writeHistory(dl.db.freezer, bottom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Determine if the persisted history object has exceeded the configured
|
||||
// limitation, set the overflow as true if so.
|
||||
tail, err := dl.db.freezer.Tail()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
limit := dl.db.config.StateHistory
|
||||
if limit != 0 && bottom.stateID()-tail > limit {
|
||||
overflow = true
|
||||
oldest = bottom.stateID() - limit + 1 // track the id of history **after truncation**
|
||||
}
|
||||
}
|
||||
// Mark the diskLayer as stale before applying any mutations on top.
|
||||
dl.stale = true
|
||||
|
||||
// Store the root->id lookup afterwards. All stored lookups are
|
||||
// identified by the **unique** state root. It's impossible that
|
||||
// in the same chain blocks are not adjacent but have the same
|
||||
// root.
|
||||
// Store the root->id lookup afterwards. All stored lookups are identified
|
||||
// by the **unique** state root. It's impossible that in the same chain
|
||||
// blocks are not adjacent but have the same root.
|
||||
if dl.id == 0 {
|
||||
rawdb.WriteStateID(dl.db.diskdb, dl.root, 0)
|
||||
}
|
||||
rawdb.WriteStateID(dl.db.diskdb, bottom.rootHash(), bottom.stateID())
|
||||
|
||||
// Construct a new disk layer by merging the nodes from the provided
|
||||
// diff layer, and flush the content in disk layer if there are too
|
||||
// many nodes cached. The clean cache is inherited from the original
|
||||
// disk layer for reusing.
|
||||
// Construct a new disk layer by merging the nodes from the provided diff
|
||||
// layer, and flush the content in disk layer if there are too many nodes
|
||||
// cached. The clean cache is inherited from the original disk layer.
|
||||
ndl := newDiskLayer(bottom.root, bottom.stateID(), dl.db, dl.cleans, dl.buffer.commit(bottom.nodes))
|
||||
err := ndl.buffer.flush(ndl.db.diskdb, ndl.cleans, ndl.id, force)
|
||||
if err != nil {
|
||||
|
||||
// In a unique scenario where the ID of the oldest history object (after tail
|
||||
// truncation) surpasses the persisted state ID, we take the necessary action
|
||||
// of forcibly committing the cached dirty nodes to ensure that the persisted
|
||||
// state ID remains higher.
|
||||
if !force && rawdb.ReadPersistentStateID(dl.db.diskdb) < oldest {
|
||||
force = true
|
||||
}
|
||||
if err := ndl.buffer.flush(ndl.db.diskdb, ndl.cleans, ndl.id, force); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// To remove outdated history objects from the end, we set the 'tail' parameter
|
||||
// to 'oldest-1' due to the offset between the freezer index and the history ID.
|
||||
if overflow {
|
||||
pruned, err := truncateFromTail(ndl.db.diskdb, ndl.db.freezer, oldest-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("Prune state history", "number", pruned)
|
||||
}
|
||||
return ndl, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -512,38 +512,28 @@ func readHistory(freezer *rawdb.ResettableFreezer, id uint64) (*history, error)
|
|||
return &dec, nil
|
||||
}
|
||||
|
||||
// writeHistory writes the state history with provided state set. After
|
||||
// storing the corresponding state history, it will also prune the stale
|
||||
// histories from the disk with the given threshold.
|
||||
func writeHistory(db ethdb.KeyValueStore, freezer *rawdb.ResettableFreezer, dl *diffLayer, limit uint64) error {
|
||||
// writeHistory persists the state history with the provided state set.
|
||||
func writeHistory(freezer *rawdb.ResettableFreezer, dl *diffLayer) error {
|
||||
// Short circuit if state set is not available.
|
||||
if dl.states == nil {
|
||||
return errors.New("state change set is not available")
|
||||
}
|
||||
var (
|
||||
err error
|
||||
n int
|
||||
start = time.Now()
|
||||
h = newHistory(dl.rootHash(), dl.parentLayer().rootHash(), dl.block, dl.states)
|
||||
start = time.Now()
|
||||
history = newHistory(dl.rootHash(), dl.parentLayer().rootHash(), dl.block, dl.states)
|
||||
)
|
||||
accountData, storageData, accountIndex, storageIndex := h.encode()
|
||||
accountData, storageData, accountIndex, storageIndex := history.encode()
|
||||
dataSize := common.StorageSize(len(accountData) + len(storageData))
|
||||
indexSize := common.StorageSize(len(accountIndex) + len(storageIndex))
|
||||
|
||||
// Write history data into five freezer table respectively.
|
||||
rawdb.WriteStateHistory(freezer, dl.stateID(), h.meta.encode(), accountIndex, storageIndex, accountData, storageData)
|
||||
rawdb.WriteStateHistory(freezer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData)
|
||||
|
||||
// Prune stale state histories based on the config.
|
||||
if limit != 0 && dl.stateID() > limit {
|
||||
n, err = truncateFromTail(db, freezer, dl.stateID()-limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
historyDataBytesMeter.Mark(int64(dataSize))
|
||||
historyIndexBytesMeter.Mark(int64(indexSize))
|
||||
historyBuildTimeMeter.UpdateSince(start)
|
||||
log.Debug("Stored state history", "id", dl.stateID(), "block", dl.block, "data", dataSize, "index", indexSize, "pruned", n, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
log.Debug("Stored state history", "id", dl.stateID(), "block", dl.block, "data", dataSize, "index", indexSize, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue