From d2ea38a5929307b61389f49e0662e5d83a860446 Mon Sep 17 00:00:00 2001 From: barryz Date: Mon, 8 Mar 2021 12:30:01 +0800 Subject: [PATCH] make triesInMemory configurable --- Makefile | 12 ++++++++--- cmd/devp2p/internal/ethtest/suite_test.go | 1 + cmd/utils/flags.go | 1 + core/blockchain.go | 26 ++++++++++++++++++++--- eth/backend.go | 1 + eth/ethconfig/config.go | 2 ++ eth/ethconfig/gen_config.go | 6 ++++++ 7 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index cb5a87dad0..9efeb524f5 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,18 @@ GOBIN = ./build/bin GO ?= latest GORUN = env GO111MODULE=on go run +PWD = `pwd` geth: $(GORUN) build/ci.go install ./cmd/geth @echo "Done building." @echo "Run \"$(GOBIN)/geth\" to launch geth." +geth-linux: + docker run --rm -v "$(PWD)":/usr/src/go-ethereum -w /usr/src/go-ethereum golang:1.16.3 $(GORUN) build/ci.go install ./cmd/geth + @echo "Done building." + @echo "Run \"$(GOBIN)/geth\" to launch geth." + all: $(GORUN) build/ci.go install @@ -60,9 +66,9 @@ geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios @echo "Full cross compilation done:" @ls -ld $(GOBIN)/geth-* -geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm geth-linux-mips64 geth-linux-mips64le - @echo "Linux cross compilation done:" - @ls -ld $(GOBIN)/geth-linux-* +# geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm geth-linux-mips64 geth-linux-mips64le +# @echo "Linux cross compilation done:" +# @ls -ld $(GOBIN)/geth-linux-* geth-linux-386: $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/386 -v ./cmd/geth diff --git a/cmd/devp2p/internal/ethtest/suite_test.go b/cmd/devp2p/internal/ethtest/suite_test.go index 6e3217151a..d0dbf0ab29 100644 --- a/cmd/devp2p/internal/ethtest/suite_test.go +++ b/cmd/devp2p/internal/ethtest/suite_test.go @@ -91,6 +91,7 @@ func setupGeth(stack *node.Node) error { Genesis: &chain.genesis, NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763 DatabaseCache: 10, + TriesInMemory: 128, TrieCleanCache: 10, TrieCleanCacheJournal: "", TrieCleanCacheRejournal: 60 * time.Minute, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 7ed5907dba..0933b6ddcf 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1855,6 +1855,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) } cache := &core.CacheConfig{ + TriesInMemory: ethconfig.Defaults.TriesInMemory, TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, TrieCleanNoPrefetch: ctx.GlobalBool(CacheNoPrefetchFlag.Name), TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, diff --git a/core/blockchain.go b/core/blockchain.go index 18e126657c..fbddba228c 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -52,6 +52,9 @@ var ( headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) + headLastGCBlockGauge = metrics.NewRegisteredGauge("chain/head/lastgc", nil) + headLastPersistGauge = metrics.NewRegisteredGauge("chain/head/lastpersist", nil) + accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil) @@ -82,6 +85,11 @@ var ( errInsertionInterrupted = errors.New("insertion is interrupted") ) +var ( + // TriesInMemory Keeps the latest 128 blocks when pruning. + TriesInMemory uint64 = 128 +) + const ( bodyCacheLimit = 256 blockCacheLimit = 256 @@ -89,7 +97,6 @@ const ( txLookupCacheLimit = 1024 maxFutureBlocks = 256 maxTimeFutureBlocks = 30 - TriesInMemory = 128 // BlockChainVersion ensures that an incompatible database forces a resync from scratch. // @@ -120,6 +127,7 @@ const ( // CacheConfig contains the configuration values for the trie caching/pruning // that's resident in a blockchain. type CacheConfig struct { + TriesInMemory int // Keeps the latest n blocks when pruning. TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory TrieCleanJournal string // Disk journal for saving clean cache entries. TrieCleanRejournal time.Duration // Time interval to dump clean cache to disk periodically @@ -136,6 +144,7 @@ type CacheConfig struct { // defaultCacheConfig are the default caching values if none are specified by the // user (also used during testing). var defaultCacheConfig = &CacheConfig{ + TriesInMemory: 128, TrieCleanLimit: 256, TrieDirtyLimit: 256, TrieTimeLimit: 5 * time.Minute, @@ -218,6 +227,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par if cacheConfig == nil { cacheConfig = defaultCacheConfig } + if cacheConfig.TriesInMemory != 0 { + TriesInMemory = uint64(cacheConfig.TriesInMemory) + } + if TriesInMemory != 128 { + log.Warn("TriesInMemory isn't the default value(128), non-default values may cause system instability", "triesInMemory", TriesInMemory) + } bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) receiptsCache, _ := lru.New(receiptsCacheLimit) @@ -1030,11 +1045,14 @@ func (bc *BlockChain) Stop() { log.Error("Failed to commit recent state trie", "err", err) } } + if !bc.triegc.Empty() { + log.Info("Dereference all trie nodes remaining in prqueue", "nodes", bc.triegc.Size()) + } for !bc.triegc.Empty() { triedb.Dereference(bc.triegc.PopItem().(common.Hash)) } if size, _ := triedb.Size(); size != 0 { - log.Error("Dangling trie nodes after full cleanup") + log.Error("Dangling trie nodes after full cleanup", "size", size) } } // Ensure all live cached entries be saved into disk, so that we can skip @@ -1511,11 +1529,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // If we're exceeding limits but haven't reached a large enough memory gap, // warn the user that the system is becoming unstable. if chosen < lastWrite+TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit { - log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/TriesInMemory) + log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/float64(TriesInMemory)) } // Flush an entire trie and restart the counters triedb.Commit(header.Root, true, nil) lastWrite = chosen + headLastPersistGauge.Update(int64(chosen)) bc.gcproc = 0 } } @@ -1526,6 +1545,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. bc.triegc.Push(root, number) break } + headLastGCBlockGauge.Update(-number) triedb.Dereference(root.(common.Hash)) } } diff --git a/eth/backend.go b/eth/backend.go index 6d7b0a7201..3b14741d02 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -177,6 +177,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { EnablePreimageRecording: config.EnablePreimageRecording, } cacheConfig = &core.CacheConfig{ + TriesInMemory: config.TriesInMemory, TrieCleanLimit: config.TrieCleanCache, TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal), TrieCleanRejournal: config.TrieCleanCacheRejournal, diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 0913b69d7f..6ce3dc29b4 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -81,6 +81,7 @@ var Defaults = Config{ TrieCleanCacheRejournal: 60 * time.Minute, TrieDirtyCache: 256, TrieTimeout: 60 * time.Minute, + TriesInMemory: 128, SnapshotCache: 102, Miner: miner.Config{ GasFloor: 8000000, @@ -165,6 +166,7 @@ type Config struct { TrieCleanCacheRejournal time.Duration `toml:",omitempty"` // Time interval to regenerate the journal for clean cache TrieDirtyCache int TrieTimeout time.Duration + TriesInMemory int SnapshotCache int Preimages bool diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 2310dd4499..f0114f040d 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -46,6 +46,7 @@ func (c Config) MarshalTOML() (interface{}, error) { TrieCleanCacheRejournal time.Duration `toml:",omitempty"` TrieDirtyCache int TrieTimeout time.Duration + TriesInMemory int SnapshotCache int Preimages bool Miner miner.Config @@ -89,6 +90,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.TrieCleanCacheRejournal = c.TrieCleanCacheRejournal enc.TrieDirtyCache = c.TrieDirtyCache enc.TrieTimeout = c.TrieTimeout + enc.TriesInMemory = c.TriesInMemory enc.SnapshotCache = c.SnapshotCache enc.Preimages = c.Preimages enc.Miner = c.Miner @@ -136,6 +138,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { TrieCleanCacheRejournal *time.Duration `toml:",omitempty"` TrieDirtyCache *int TrieTimeout *time.Duration + TriesInMemory *int SnapshotCache *int Preimages *bool Miner *miner.Config @@ -238,6 +241,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.TrieTimeout != nil { c.TrieTimeout = *dec.TrieTimeout } + if dec.TriesInMemory != nil { + c.TriesInMemory = *dec.TriesInMemory + } if dec.SnapshotCache != nil { c.SnapshotCache = *dec.SnapshotCache }