cmd/utils, consensus/beacon, core/state: when configured via stub flag: prefetch all reads from account/storage tries, terminate prefetcher synchronously.

This commit is contained in:
Jared Wasinger 2024-05-19 21:16:11 -07:00 committed by Péter Szilágyi
parent 0750cb0c8f
commit 3e56c3eea1
7 changed files with 34 additions and 12 deletions

View file

@ -156,6 +156,7 @@ var (
utils.BeaconGenesisRootFlag, utils.BeaconGenesisRootFlag,
utils.BeaconGenesisTimeFlag, utils.BeaconGenesisTimeFlag,
utils.BeaconCheckpointFlag, utils.BeaconCheckpointFlag,
utils.DebugCollectWitnessFlag,
}, utils.NetworkFlags, utils.DatabaseFlags) }, utils.NetworkFlags, utils.DatabaseFlags)
rpcFlags = []cli.Flag{ rpcFlags = []cli.Flag{

View file

@ -604,6 +604,11 @@ var (
Usage: "Disables db compaction after import", Usage: "Disables db compaction after import",
Category: flags.LoggingCategory, Category: flags.LoggingCategory,
} }
DebugCollectWitnessFlag = &cli.BoolFlag{
Name: "collectwitnesses",
Usage: "Enable state witness generation during block execution. Work in progress flag, don't use.",
Category: flags.MiscCategory,
}
// MISC settings // MISC settings
SyncTargetFlag = &cli.StringFlag{ SyncTargetFlag = &cli.StringFlag{
@ -2204,6 +2209,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
vmcfg.Tracer = t vmcfg.Tracer = t
} }
} }
vmcfg.EnableWitnessCollection = ctx.Bool(DebugCollectWitnessFlag.Name)
// Disable transaction indexing/unindexing by default. // Disable transaction indexing/unindexing by default.
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil) chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
if err != nil { if err != nil {

View file

@ -1809,7 +1809,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
// while processing transactions. Before Byzantium the prefetcher is mostly // while processing transactions. Before Byzantium the prefetcher is mostly
// useless due to the intermediate root hashing after each transaction. // useless due to the intermediate root hashing after each transaction.
if bc.chainConfig.IsByzantium(block.Number()) { if bc.chainConfig.IsByzantium(block.Number()) {
statedb.StartPrefetcher("chain") statedb.StartPrefetcher("chain", bc.vmConfig.EnableWitnessCollection)
} }
activeState = statedb activeState = statedb

View file

@ -212,6 +212,9 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
} }
value.SetBytes(content) value.SetBytes(content)
} }
if s.data.Root != types.EmptyRootHash {
s.db.prefetcher.prefetchWitness(s.addrHash, s.origin.Root, s.address, [][]byte{key[:]})
}
} }
// If the snapshot is unavailable or reading from it fails, load from the database. // If the snapshot is unavailable or reading from it fails, load from the database.
if s.db.snap == nil || err != nil { if s.db.snap == nil || err != nil {

View file

@ -200,14 +200,14 @@ func (s *StateDB) SetLogger(l *tracing.Hooks) {
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the // state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot. // commit phase, most of the needed data is already hot.
func (s *StateDB) StartPrefetcher(namespace string) { func (s *StateDB) StartPrefetcher(namespace string, collectWitnesses bool) {
if s.prefetcher != nil { if s.prefetcher != nil {
s.prefetcher.terminate(false) s.prefetcher.terminate(false)
s.prefetcher.report() s.prefetcher.report()
s.prefetcher = nil s.prefetcher = nil
} }
if s.snap != nil { if s.snap != nil {
s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace) s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace, collectWitnesses)
// With the switch to the Proof-of-Stake consensus algorithm, block production // With the switch to the Proof-of-Stake consensus algorithm, block production
// rewards are now handled at the consensus layer. Consequently, a block may // rewards are now handled at the consensus layer. Consequently, a block may
@ -587,6 +587,7 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
if acc == nil { if acc == nil {
return nil return nil
} }
s.prefetcher.prefetchWitness(common.Hash{}, s.originalRoot, common.Address{}, [][]byte{addr[:]})
data = &types.StateAccount{ data = &types.StateAccount{
Nonce: acc.Nonce, Nonce: acc.Nonce,
Balance: acc.Balance, Balance: acc.Balance,

View file

@ -40,10 +40,11 @@ var (
// //
// Note, the prefetcher's API is not thread safe. // Note, the prefetcher's API is not thread safe.
type triePrefetcher struct { type triePrefetcher struct {
db Database // Database to fetch trie nodes through db Database // Database to fetch trie nodes through
root common.Hash // Root hash of the account trie for metrics root common.Hash // Root hash of the account trie for metrics
fetchers map[string]*subfetcher // Subfetchers for each trie fetchers map[string]*subfetcher // Subfetchers for each trie
term chan struct{} // Channel to signal interruption term chan struct{} // Channel to signal interruption
collectWitnesses bool // whether to allow prefetch calls for witness collection
deliveryMissMeter metrics.Meter deliveryMissMeter metrics.Meter
accountLoadMeter metrics.Meter accountLoadMeter metrics.Meter
@ -54,13 +55,14 @@ type triePrefetcher struct {
storageWasteMeter metrics.Meter storageWasteMeter metrics.Meter
} }
func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePrefetcher { func newTriePrefetcher(db Database, root common.Hash, namespace string, collectWitnesses bool) *triePrefetcher {
prefix := triePrefetchMetricsPrefix + namespace prefix := triePrefetchMetricsPrefix + namespace
return &triePrefetcher{ return &triePrefetcher{
db: db, db: db,
root: root, root: root,
fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map
term: make(chan struct{}), term: make(chan struct{}),
collectWitnesses: collectWitnesses,
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil), deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil), accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil),
@ -142,6 +144,14 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr comm
return fetcher.schedule(keys) return fetcher.schedule(keys)
} }
// prefetchWitness calls prefetch if witness collection is enabled.
func (p *triePrefetcher) prefetchWitness(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) error {
if p.collectWitnesses {
return p.prefetch(owner, root, addr, keys)
}
return nil
}
// trie returns the trie matching the root hash, blocking until the fetcher of // trie returns the trie matching the root hash, blocking until the fetcher of
// the given trie terminates. If no fetcher exists for the request, nil will be // the given trie terminates. If no fetcher exists for the request, nil will be
// returned. // returned.

View file

@ -33,6 +33,7 @@ type Config struct {
NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls) NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls)
EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages
ExtraEips []int // Additional EIPS that are to be enabled ExtraEips []int // Additional EIPS that are to be enabled
EnableWitnessCollection bool // true if witness collection is enabled
} }
// ScopeContext contains the things that are per-call, such as stack and memory, // ScopeContext contains the things that are per-call, such as stack and memory,