cmd, core, eth: support disabling the concurrent state prefetcher

This commit is contained in:
Péter Szilágyi 2019-04-01 11:52:11 +03:00
parent bb9631c399
commit ed34a5e08a
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
6 changed files with 40 additions and 21 deletions

View File

@ -102,6 +102,7 @@ var (
utils.CacheDatabaseFlag, utils.CacheDatabaseFlag,
utils.CacheTrieFlag, utils.CacheTrieFlag,
utils.CacheGCFlag, utils.CacheGCFlag,
utils.CacheNoPrefetchFlag,
utils.ListenPortFlag, utils.ListenPortFlag,
utils.MaxPeersFlag, utils.MaxPeersFlag,
utils.MaxPendingPeersFlag, utils.MaxPendingPeersFlag,

View File

@ -139,6 +139,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.CacheDatabaseFlag, utils.CacheDatabaseFlag,
utils.CacheTrieFlag, utils.CacheTrieFlag,
utils.CacheGCFlag, utils.CacheGCFlag,
utils.CacheNoPrefetchFlag,
}, },
}, },
{ {

View File

@ -349,6 +349,10 @@ var (
Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
Value: 25, Value: 25,
} }
CacheNoPrefetchFlag = cli.BoolFlag{
Name: "cache.noprefetch",
Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
}
// Miner settings // Miner settings
MiningEnabledFlag = cli.BoolFlag{ MiningEnabledFlag = cli.BoolFlag{
Name: "mine", Name: "mine",
@ -1336,6 +1340,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name)
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
@ -1595,10 +1600,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
cache := &core.CacheConfig{ cache := &core.CacheConfig{
Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", TrieCleanLimit: eth.DefaultConfig.TrieCleanCache,
TrieCleanLimit: eth.DefaultConfig.TrieCleanCache, TrieCleanNoPrefetch: ctx.GlobalBool(CacheNoPrefetchFlag.Name),
TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache, TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache,
TrieTimeLimit: eth.DefaultConfig.TrieTimeout, TrieDirtyDisabled: ctx.GlobalString(GCModeFlag.Name) == "archive",
TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
} }
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100

View File

@ -90,10 +90,11 @@ const (
// CacheConfig contains the configuration values for the trie caching/pruning // CacheConfig contains the configuration values for the trie caching/pruning
// that's resident in a blockchain. // that's resident in a blockchain.
type CacheConfig struct { type CacheConfig struct {
Disabled bool // Whether to disable trie write caching (archive node) TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
} }
// BlockChain represents the canonical chain given a database with a genesis // BlockChain represents the canonical chain given a database with a genesis
@ -708,7 +709,7 @@ func (bc *BlockChain) Stop() {
// - HEAD: So we don't need to reprocess any blocks in the general case // - HEAD: So we don't need to reprocess any blocks in the general case
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted // - HEAD-127: So we have a hard limit on the number of blocks reexecuted
if !bc.cacheConfig.Disabled { if !bc.cacheConfig.TrieDirtyDisabled {
triedb := bc.stateCache.TrieDB() triedb := bc.stateCache.TrieDB()
for _, offset := range []uint64{0, 1, triesInMemory - 1} { for _, offset := range []uint64{0, 1, triesInMemory - 1} {
@ -968,7 +969,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
triedb := bc.stateCache.TrieDB() triedb := bc.stateCache.TrieDB()
// If we're running an archive node, always flush // If we're running an archive node, always flush
if bc.cacheConfig.Disabled { if bc.cacheConfig.TrieDirtyDisabled {
if err := triedb.Commit(root, false); err != nil { if err := triedb.Commit(root, false); err != nil {
return NonStatTy, err return NonStatTy, err
} }
@ -1232,16 +1233,18 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
// transactions and probabilistically some of the account/storage trie nodes. // transactions and probabilistically some of the account/storage trie nodes.
var followupInterrupt uint32 var followupInterrupt uint32
if followup, err := it.peek(); followup != nil && err == nil { if !bc.cacheConfig.TrieCleanNoPrefetch {
go func(start time.Time) { if followup, err := it.peek(); followup != nil && err == nil {
throwaway, _ := state.New(parent.Root, bc.stateCache) go func(start time.Time) {
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) throwaway, _ := state.New(parent.Root, bc.stateCache)
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)
blockPrefetchExecuteTimer.Update(time.Since(start)) blockPrefetchExecuteTimer.Update(time.Since(start))
if atomic.LoadUint32(&followupInterrupt) == 1 { if atomic.LoadUint32(&followupInterrupt) == 1 {
blockPrefetchInterruptMeter.Mark(1) blockPrefetchInterruptMeter.Mark(1)
} }
}(time.Now()) }(time.Now())
}
} }
// Process block using the parent state as reference point // Process block using the parent state as reference point
substart := time.Now() substart := time.Now()

View File

@ -165,7 +165,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
EWASMInterpreter: config.EWASMInterpreter, EWASMInterpreter: config.EWASMInterpreter,
EVMInterpreter: config.EVMInterpreter, EVMInterpreter: config.EVMInterpreter,
} }
cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout} cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache,
TrieCleanNoPrefetch: config.NoPrefetch,
TrieDirtyLimit: config.TrieDirtyCache,
TrieDirtyDisabled: config.NoPruning,
TrieTimeLimit: config.TrieTimeout,
}
) )
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve)
if err != nil { if err != nil {

View File

@ -92,7 +92,9 @@ type Config struct {
// Protocol options // Protocol options
NetworkId uint64 // Network ID to use for selecting peers to connect to NetworkId uint64 // Network ID to use for selecting peers to connect to
SyncMode downloader.SyncMode SyncMode downloader.SyncMode
NoPruning bool
NoPruning bool // Whether to disable pruning and flush everything to disk
NoPrefetch bool // Whether to disable prefetching and only load state on demand
// Whitelist of required block number -> hash values to accept // Whitelist of required block number -> hash values to accept
Whitelist map[uint64]common.Hash `toml:"-"` Whitelist map[uint64]common.Hash `toml:"-"`