mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
Revert "cmd, core, eth, graphql, trie: no persisted clean trie cache file (#27525)"
This reverts commit 2c0c010df5.
This commit is contained in:
parent
4e40557ff8
commit
923d43b402
13 changed files with 186 additions and 59 deletions
|
|
@ -109,13 +109,15 @@ func setupGeth(stack *node.Node) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
backend, err := eth.New(stack, ðconfig.Config{
|
backend, err := eth.New(stack, ðconfig.Config{
|
||||||
Genesis: &chain.genesis,
|
Genesis: &chain.genesis,
|
||||||
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
|
NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763
|
||||||
DatabaseCache: 10,
|
DatabaseCache: 10,
|
||||||
TrieCleanCache: 10,
|
TrieCleanCache: 10,
|
||||||
TrieDirtyCache: 16,
|
TrieCleanCacheJournal: "",
|
||||||
TrieTimeout: 60 * time.Minute,
|
TrieCleanCacheRejournal: 60 * time.Minute,
|
||||||
SnapshotCache: 10,
|
TrieDirtyCache: 16,
|
||||||
|
TrieTimeout: 60 * time.Minute,
|
||||||
|
SnapshotCache: 10,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -276,10 +276,6 @@ func deprecated(field string) bool {
|
||||||
return true
|
return true
|
||||||
case "ethconfig.Config.EWASMInterpreter":
|
case "ethconfig.Config.EWASMInterpreter":
|
||||||
return true
|
return true
|
||||||
case "ethconfig.Config.TrieCleanCacheJournal":
|
|
||||||
return true
|
|
||||||
case "ethconfig.Config.TrieCleanCacheRejournal":
|
|
||||||
return true
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ var (
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: pruneState,
|
Action: pruneState,
|
||||||
Flags: flags.Merge([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
|
utils.CacheTrieJournalFlag,
|
||||||
utils.BloomFilterSizeFlag,
|
utils.BloomFilterSizeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
}, utils.NetworkFlags, utils.DatabasePathFlags),
|
||||||
Description: `
|
Description: `
|
||||||
|
|
@ -159,7 +160,7 @@ block is used.
|
||||||
// Deprecation: this command should be deprecated once the hash-based
|
// Deprecation: this command should be deprecated once the hash-based
|
||||||
// scheme is deprecated.
|
// scheme is deprecated.
|
||||||
func pruneState(ctx *cli.Context) error {
|
func pruneState(ctx *cli.Context) error {
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, config := makeConfigNode(ctx)
|
||||||
defer stack.Close()
|
defer stack.Close()
|
||||||
|
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
|
|
@ -167,6 +168,7 @@ func pruneState(ctx *cli.Context) error {
|
||||||
|
|
||||||
prunerconfig := pruner.Config{
|
prunerconfig := pruner.Config{
|
||||||
Datadir: stack.ResolvePath(""),
|
Datadir: stack.ResolvePath(""),
|
||||||
|
Cachedir: stack.ResolvePath(config.Eth.TrieCleanCacheJournal),
|
||||||
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
|
BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name),
|
||||||
}
|
}
|
||||||
pruner, err := pruner.NewPruner(chaindb, prunerconfig)
|
pruner, err := pruner.NewPruner(chaindb, prunerconfig)
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,18 @@ var (
|
||||||
Value: 15,
|
Value: 15,
|
||||||
Category: flags.PerfCategory,
|
Category: flags.PerfCategory,
|
||||||
}
|
}
|
||||||
|
CacheTrieJournalFlag = &cli.StringFlag{
|
||||||
|
Name: "cache.trie.journal",
|
||||||
|
Usage: "Disk journal directory for trie cache to survive node restarts",
|
||||||
|
Value: ethconfig.Defaults.TrieCleanCacheJournal,
|
||||||
|
Category: flags.PerfCategory,
|
||||||
|
}
|
||||||
|
CacheTrieRejournalFlag = &cli.DurationFlag{
|
||||||
|
Name: "cache.trie.rejournal",
|
||||||
|
Usage: "Time interval to regenerate the trie cache journal",
|
||||||
|
Value: ethconfig.Defaults.TrieCleanCacheRejournal,
|
||||||
|
Category: flags.PerfCategory,
|
||||||
|
}
|
||||||
CacheGCFlag = &cli.IntFlag{
|
CacheGCFlag = &cli.IntFlag{
|
||||||
Name: "cache.gc",
|
Name: "cache.gc",
|
||||||
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)",
|
||||||
|
|
@ -1698,6 +1710,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||||
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(CacheTrieJournalFlag.Name) {
|
||||||
|
cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.IsSet(CacheTrieRejournalFlag.Name) {
|
||||||
|
cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name)
|
||||||
|
}
|
||||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||||
cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@ var ShowDeprecated = &cli.Command{
|
||||||
|
|
||||||
var DeprecatedFlags = []cli.Flag{
|
var DeprecatedFlags = []cli.Flag{
|
||||||
NoUSBFlag,
|
NoUSBFlag,
|
||||||
CacheTrieJournalFlag,
|
|
||||||
CacheTrieRejournalFlag,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -44,17 +42,6 @@ var (
|
||||||
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
// (Deprecated June 2023, shown in aliased flags section)
|
|
||||||
CacheTrieJournalFlag = &cli.StringFlag{
|
|
||||||
Name: "cache.trie.journal",
|
|
||||||
Usage: "Disk journal directory for trie cache to survive node restarts",
|
|
||||||
Category: flags.PerfCategory,
|
|
||||||
}
|
|
||||||
CacheTrieRejournalFlag = &cli.DurationFlag{
|
|
||||||
Name: "cache.trie.rejournal",
|
|
||||||
Usage: "Time interval to regenerate the trie cache journal",
|
|
||||||
Category: flags.PerfCategory,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,8 @@ const (
|
||||||
// that's resident in a blockchain.
|
// that's resident in a blockchain.
|
||||||
type CacheConfig struct {
|
type CacheConfig struct {
|
||||||
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
|
||||||
|
TrieCleanJournal string // Disk journal for saving clean cache entries.
|
||||||
|
TrieCleanRejournal time.Duration // Time interval to dump clean cache to disk periodically
|
||||||
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
|
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
|
||||||
TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
|
TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
|
||||||
|
|
@ -236,6 +238,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
// Open trie database with provided config
|
// Open trie database with provided config
|
||||||
triedb := trie.NewDatabaseWithConfig(db, &trie.Config{
|
triedb := trie.NewDatabaseWithConfig(db, &trie.Config{
|
||||||
Cache: cacheConfig.TrieCleanLimit,
|
Cache: cacheConfig.TrieCleanLimit,
|
||||||
|
Journal: cacheConfig.TrieCleanJournal,
|
||||||
Preimages: cacheConfig.Preimages,
|
Preimages: cacheConfig.Preimages,
|
||||||
})
|
})
|
||||||
// Setup the genesis block, commit the provided genesis specification
|
// Setup the genesis block, commit the provided genesis specification
|
||||||
|
|
@ -408,6 +411,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
bc.wg.Add(1)
|
bc.wg.Add(1)
|
||||||
go bc.updateFutureBlocks()
|
go bc.updateFutureBlocks()
|
||||||
|
|
||||||
|
// If periodic cache journal is required, spin it up.
|
||||||
|
if bc.cacheConfig.TrieCleanRejournal > 0 {
|
||||||
|
if bc.cacheConfig.TrieCleanRejournal < time.Minute {
|
||||||
|
log.Warn("Sanitizing invalid trie cache journal time", "provided", bc.cacheConfig.TrieCleanRejournal, "updated", time.Minute)
|
||||||
|
bc.cacheConfig.TrieCleanRejournal = time.Minute
|
||||||
|
}
|
||||||
|
bc.wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer bc.wg.Done()
|
||||||
|
bc.triedb.SaveCachePeriodically(bc.cacheConfig.TrieCleanJournal, bc.cacheConfig.TrieCleanRejournal, bc.quit)
|
||||||
|
}()
|
||||||
|
}
|
||||||
// Rewind the chain in case of an incompatible config upgrade.
|
// Rewind the chain in case of an incompatible config upgrade.
|
||||||
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
||||||
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
||||||
|
|
@ -972,6 +987,11 @@ func (bc *BlockChain) Stop() {
|
||||||
if err := bc.stateCache.TrieDB().Close(); err != nil {
|
if err := bc.stateCache.TrieDB().Close(); err != nil {
|
||||||
log.Error("Failed to close trie db", "err", err)
|
log.Error("Failed to close trie db", "err", err)
|
||||||
}
|
}
|
||||||
|
// Ensure all live cached entries be saved into disk, so that we can skip
|
||||||
|
// cache warmup when node restarts.
|
||||||
|
if bc.cacheConfig.TrieCleanJournal != "" {
|
||||||
|
bc.triedb.SaveCache(bc.cacheConfig.TrieCleanJournal)
|
||||||
|
}
|
||||||
log.Info("Blockchain stopped")
|
log.Info("Blockchain stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ const (
|
||||||
// Config includes all the configurations for pruning.
|
// Config includes all the configurations for pruning.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Datadir string // The directory of the state database
|
Datadir string // The directory of the state database
|
||||||
|
Cachedir string // The directory of state clean cache
|
||||||
BloomSize uint64 // The Megabytes of memory allocated to bloom-filter
|
BloomSize uint64 // The Megabytes of memory allocated to bloom-filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +241,7 @@ func (p *Pruner) Prune(root common.Hash) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if stateBloomRoot != (common.Hash{}) {
|
if stateBloomRoot != (common.Hash{}) {
|
||||||
return RecoverPruning(p.config.Datadir, p.db)
|
return RecoverPruning(p.config.Datadir, p.db, p.config.Cachedir)
|
||||||
}
|
}
|
||||||
// If the target state root is not specified, use the HEAD-127 as the
|
// If the target state root is not specified, use the HEAD-127 as the
|
||||||
// target. The reason for picking it is:
|
// target. The reason for picking it is:
|
||||||
|
|
@ -298,6 +299,12 @@ func (p *Pruner) Prune(root common.Hash) error {
|
||||||
log.Info("Selecting user-specified state as the pruning target", "root", root)
|
log.Info("Selecting user-specified state as the pruning target", "root", root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Before start the pruning, delete the clean trie cache first.
|
||||||
|
// It's necessary otherwise in the next restart we will hit the
|
||||||
|
// deleted state root in the "clean cache" so that the incomplete
|
||||||
|
// state is picked for usage.
|
||||||
|
deleteCleanTrieCache(p.config.Cachedir)
|
||||||
|
|
||||||
// All the state roots of the middle layer should be forcibly pruned,
|
// All the state roots of the middle layer should be forcibly pruned,
|
||||||
// otherwise the dangling state will be left.
|
// otherwise the dangling state will be left.
|
||||||
middleRoots := make(map[common.Hash]struct{})
|
middleRoots := make(map[common.Hash]struct{})
|
||||||
|
|
@ -335,7 +342,7 @@ func (p *Pruner) Prune(root common.Hash) error {
|
||||||
// pruning can be resumed. What's more if the bloom filter is constructed, the
|
// pruning can be resumed. What's more if the bloom filter is constructed, the
|
||||||
// pruning **has to be resumed**. Otherwise a lot of dangling nodes may be left
|
// pruning **has to be resumed**. Otherwise a lot of dangling nodes may be left
|
||||||
// in the disk.
|
// in the disk.
|
||||||
func RecoverPruning(datadir string, db ethdb.Database) error {
|
func RecoverPruning(datadir string, db ethdb.Database, trieCachePath string) error {
|
||||||
stateBloomPath, stateBloomRoot, err := findBloomFilter(datadir)
|
stateBloomPath, stateBloomRoot, err := findBloomFilter(datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -371,6 +378,12 @@ func RecoverPruning(datadir string, db ethdb.Database) error {
|
||||||
}
|
}
|
||||||
log.Info("Loaded state bloom filter", "path", stateBloomPath)
|
log.Info("Loaded state bloom filter", "path", stateBloomPath)
|
||||||
|
|
||||||
|
// Before start the pruning, delete the clean trie cache first.
|
||||||
|
// It's necessary otherwise in the next restart we will hit the
|
||||||
|
// deleted state root in the "clean cache" so that the incomplete
|
||||||
|
// state is picked for usage.
|
||||||
|
deleteCleanTrieCache(trieCachePath)
|
||||||
|
|
||||||
// All the state roots of the middle layers should be forcibly pruned,
|
// All the state roots of the middle layers should be forcibly pruned,
|
||||||
// otherwise the dangling state will be left.
|
// otherwise the dangling state will be left.
|
||||||
var (
|
var (
|
||||||
|
|
@ -484,3 +497,23 @@ func findBloomFilter(datadir string) (string, common.Hash, error) {
|
||||||
}
|
}
|
||||||
return stateBloomPath, stateBloomRoot, nil
|
return stateBloomPath, stateBloomRoot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const warningLog = `
|
||||||
|
|
||||||
|
WARNING!
|
||||||
|
|
||||||
|
The clean trie cache is not found. Please delete it by yourself after the
|
||||||
|
pruning. Remember don't start the Geth without deleting the clean trie cache
|
||||||
|
otherwise the entire database may be damaged!
|
||||||
|
|
||||||
|
Check the command description "geth snapshot prune-state --help" for more details.
|
||||||
|
`
|
||||||
|
|
||||||
|
func deleteCleanTrieCache(path string) {
|
||||||
|
if !common.FileExist(path) {
|
||||||
|
log.Warn(warningLog)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
os.RemoveAll(path)
|
||||||
|
log.Info("Deleted trie clean cache", "path", path)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil {
|
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
|
||||||
log.Error("Failed to recover state", "error", err)
|
log.Error("Failed to recover state", "error", err)
|
||||||
}
|
}
|
||||||
// Transfer mining-related config to the ethash config.
|
// Transfer mining-related config to the ethash config.
|
||||||
|
|
@ -184,6 +184,8 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
cacheConfig = &core.CacheConfig{
|
cacheConfig = &core.CacheConfig{
|
||||||
TrieCleanLimit: config.TrieCleanCache,
|
TrieCleanLimit: config.TrieCleanCache,
|
||||||
|
TrieCleanJournal: stack.ResolvePath(config.TrieCleanCacheJournal),
|
||||||
|
TrieCleanRejournal: config.TrieCleanCacheRejournal,
|
||||||
TrieCleanNoPrefetch: config.NoPrefetch,
|
TrieCleanNoPrefetch: config.NoPrefetch,
|
||||||
TrieDirtyLimit: config.TrieDirtyCache,
|
TrieDirtyLimit: config.TrieDirtyCache,
|
||||||
TrieDirtyDisabled: config.NoPruning,
|
TrieDirtyDisabled: config.NoPruning,
|
||||||
|
|
|
||||||
|
|
@ -57,23 +57,25 @@ var LightClientGPO = gasprice.Config{
|
||||||
|
|
||||||
// Defaults contains default settings for use on the Ethereum main net.
|
// Defaults contains default settings for use on the Ethereum main net.
|
||||||
var Defaults = Config{
|
var Defaults = Config{
|
||||||
SyncMode: downloader.SnapSync,
|
SyncMode: downloader.SnapSync,
|
||||||
NetworkId: 1,
|
NetworkId: 1,
|
||||||
TxLookupLimit: 2350000,
|
TxLookupLimit: 2350000,
|
||||||
LightPeers: 100,
|
LightPeers: 100,
|
||||||
UltraLightFraction: 75,
|
UltraLightFraction: 75,
|
||||||
DatabaseCache: 512,
|
DatabaseCache: 512,
|
||||||
TrieCleanCache: 154,
|
TrieCleanCache: 154,
|
||||||
TrieDirtyCache: 256,
|
TrieCleanCacheJournal: "triecache",
|
||||||
TrieTimeout: 60 * time.Minute,
|
TrieCleanCacheRejournal: 60 * time.Minute,
|
||||||
SnapshotCache: 102,
|
TrieDirtyCache: 256,
|
||||||
FilterLogCacheSize: 32,
|
TrieTimeout: 60 * time.Minute,
|
||||||
Miner: miner.DefaultConfig,
|
SnapshotCache: 102,
|
||||||
TxPool: legacypool.DefaultConfig,
|
FilterLogCacheSize: 32,
|
||||||
RPCGasCap: 50000000,
|
Miner: miner.DefaultConfig,
|
||||||
RPCEVMTimeout: 5 * time.Second,
|
TxPool: legacypool.DefaultConfig,
|
||||||
GPO: FullNodeGPO,
|
RPCGasCap: 50000000,
|
||||||
RPCTxFeeCap: 1, // 1 ether
|
RPCEVMTimeout: 5 * time.Second,
|
||||||
|
GPO: FullNodeGPO,
|
||||||
|
RPCTxFeeCap: 1, // 1 ether
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
|
//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go
|
||||||
|
|
@ -122,11 +124,13 @@ type Config struct {
|
||||||
DatabaseCache int
|
DatabaseCache int
|
||||||
DatabaseFreezer string
|
DatabaseFreezer string
|
||||||
|
|
||||||
TrieCleanCache int
|
TrieCleanCache int
|
||||||
TrieDirtyCache int
|
TrieCleanCacheJournal string `toml:",omitempty"` // Disk journal directory for trie cache to survive node restarts
|
||||||
TrieTimeout time.Duration
|
TrieCleanCacheRejournal time.Duration `toml:",omitempty"` // Time interval to regenerate the journal for clean cache
|
||||||
SnapshotCache int
|
TrieDirtyCache int
|
||||||
Preimages bool
|
TrieTimeout time.Duration
|
||||||
|
SnapshotCache int
|
||||||
|
Preimages bool
|
||||||
|
|
||||||
// This is the number of blocks for which logs will be cached in the filter system.
|
// This is the number of blocks for which logs will be cached in the filter system.
|
||||||
FilterLogCacheSize int
|
FilterLogCacheSize int
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
DatabaseCache int
|
DatabaseCache int
|
||||||
DatabaseFreezer string
|
DatabaseFreezer string
|
||||||
TrieCleanCache int
|
TrieCleanCache int
|
||||||
|
TrieCleanCacheJournal string `toml:",omitempty"`
|
||||||
|
TrieCleanCacheRejournal time.Duration `toml:",omitempty"`
|
||||||
TrieDirtyCache int
|
TrieDirtyCache int
|
||||||
TrieTimeout time.Duration
|
TrieTimeout time.Duration
|
||||||
SnapshotCache int
|
SnapshotCache int
|
||||||
|
|
@ -79,6 +81,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.DatabaseCache = c.DatabaseCache
|
enc.DatabaseCache = c.DatabaseCache
|
||||||
enc.DatabaseFreezer = c.DatabaseFreezer
|
enc.DatabaseFreezer = c.DatabaseFreezer
|
||||||
enc.TrieCleanCache = c.TrieCleanCache
|
enc.TrieCleanCache = c.TrieCleanCache
|
||||||
|
enc.TrieCleanCacheJournal = c.TrieCleanCacheJournal
|
||||||
|
enc.TrieCleanCacheRejournal = c.TrieCleanCacheRejournal
|
||||||
enc.TrieDirtyCache = c.TrieDirtyCache
|
enc.TrieDirtyCache = c.TrieDirtyCache
|
||||||
enc.TrieTimeout = c.TrieTimeout
|
enc.TrieTimeout = c.TrieTimeout
|
||||||
enc.SnapshotCache = c.SnapshotCache
|
enc.SnapshotCache = c.SnapshotCache
|
||||||
|
|
@ -123,6 +127,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
DatabaseCache *int
|
DatabaseCache *int
|
||||||
DatabaseFreezer *string
|
DatabaseFreezer *string
|
||||||
TrieCleanCache *int
|
TrieCleanCache *int
|
||||||
|
TrieCleanCacheJournal *string `toml:",omitempty"`
|
||||||
|
TrieCleanCacheRejournal *time.Duration `toml:",omitempty"`
|
||||||
TrieDirtyCache *int
|
TrieDirtyCache *int
|
||||||
TrieTimeout *time.Duration
|
TrieTimeout *time.Duration
|
||||||
SnapshotCache *int
|
SnapshotCache *int
|
||||||
|
|
@ -212,6 +218,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.TrieCleanCache != nil {
|
if dec.TrieCleanCache != nil {
|
||||||
c.TrieCleanCache = *dec.TrieCleanCache
|
c.TrieCleanCache = *dec.TrieCleanCache
|
||||||
}
|
}
|
||||||
|
if dec.TrieCleanCacheJournal != nil {
|
||||||
|
c.TrieCleanCacheJournal = *dec.TrieCleanCacheJournal
|
||||||
|
}
|
||||||
|
if dec.TrieCleanCacheRejournal != nil {
|
||||||
|
c.TrieCleanCacheRejournal = *dec.TrieCleanCacheRejournal
|
||||||
|
}
|
||||||
if dec.TrieDirtyCache != nil {
|
if dec.TrieDirtyCache != nil {
|
||||||
c.TrieDirtyCache = *dec.TrieDirtyCache
|
c.TrieDirtyCache = *dec.TrieDirtyCache
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -438,12 +438,14 @@ func createNode(t *testing.T) *node.Node {
|
||||||
|
|
||||||
func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Genesis, genBlocks int, genfunc func(i int, gen *core.BlockGen)) (*handler, []*types.Block) {
|
func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Genesis, genBlocks int, genfunc func(i int, gen *core.BlockGen)) (*handler, []*types.Block) {
|
||||||
ethConf := ðconfig.Config{
|
ethConf := ðconfig.Config{
|
||||||
Genesis: gspec,
|
Genesis: gspec,
|
||||||
NetworkId: 1337,
|
NetworkId: 1337,
|
||||||
TrieCleanCache: 5,
|
TrieCleanCache: 5,
|
||||||
TrieDirtyCache: 5,
|
TrieCleanCacheJournal: "triecache",
|
||||||
TrieTimeout: 60 * time.Minute,
|
TrieCleanCacheRejournal: 60 * time.Minute,
|
||||||
SnapshotCache: 5,
|
TrieDirtyCache: 5,
|
||||||
|
TrieTimeout: 60 * time.Minute,
|
||||||
|
SnapshotCache: 5,
|
||||||
}
|
}
|
||||||
ethBackend, err := eth.New(stack, ethConf)
|
ethBackend, err := eth.New(stack, ethConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ func getChain() *core.BlockChain {
|
||||||
TrieDirtyLimit: 0,
|
TrieDirtyLimit: 0,
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
TrieCleanNoPrefetch: true,
|
TrieCleanNoPrefetch: true,
|
||||||
|
TrieCleanRejournal: 0,
|
||||||
SnapshotLimit: 100,
|
SnapshotLimit: 100,
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,22 @@ package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/fastcache"
|
"github.com/VictoriaMetrics/fastcache"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
|
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config defines all necessary options for database.
|
// Config defines all necessary options for database.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Cache int // Memory allowance (MB) to use for caching trie nodes in memory
|
Cache int // Memory allowance (MB) to use for caching trie nodes in memory
|
||||||
Preimages bool // Flag whether the preimage of trie key is recorded
|
Journal string // Journal of clean cache to survive node restarts
|
||||||
|
Preimages bool // Flag whether the preimage of trie key is recorded
|
||||||
}
|
}
|
||||||
|
|
||||||
// backend defines the methods needed to access/update trie nodes in different
|
// backend defines the methods needed to access/update trie nodes in different
|
||||||
|
|
@ -75,7 +79,11 @@ type Database struct {
|
||||||
func prepare(diskdb ethdb.Database, config *Config) *Database {
|
func prepare(diskdb ethdb.Database, config *Config) *Database {
|
||||||
var cleans *fastcache.Cache
|
var cleans *fastcache.Cache
|
||||||
if config != nil && config.Cache > 0 {
|
if config != nil && config.Cache > 0 {
|
||||||
cleans = fastcache.New(config.Cache * 1024 * 1024)
|
if config.Journal == "" {
|
||||||
|
cleans = fastcache.New(config.Cache * 1024 * 1024)
|
||||||
|
} else {
|
||||||
|
cleans = fastcache.LoadFromFileOrNew(config.Journal, config.Cache*1024*1024)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var preimages *preimageStore
|
var preimages *preimageStore
|
||||||
if config != nil && config.Preimages {
|
if config != nil && config.Preimages {
|
||||||
|
|
@ -171,6 +179,46 @@ func (db *Database) WritePreimages() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// saveCache saves clean state cache to given directory path
|
||||||
|
// using specified CPU cores.
|
||||||
|
func (db *Database) saveCache(dir string, threads int) error {
|
||||||
|
if db.cleans == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Info("Writing clean trie cache to disk", "path", dir, "threads", threads)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
err := db.cleans.SaveToFileConcurrent(dir, threads)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to persist clean trie cache", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("Persisted the clean trie cache", "path", dir, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveCache atomically saves fast cache data to the given dir using all
|
||||||
|
// available CPU cores.
|
||||||
|
func (db *Database) SaveCache(dir string) error {
|
||||||
|
return db.saveCache(dir, runtime.GOMAXPROCS(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveCachePeriodically atomically saves fast cache data to the given dir with
|
||||||
|
// the specified interval. All dump operation will only use a single CPU core.
|
||||||
|
func (db *Database) SaveCachePeriodically(dir string, interval time.Duration, stopCh <-chan struct{}) {
|
||||||
|
ticker := time.NewTicker(interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
db.saveCache(dir, 1)
|
||||||
|
case <-stopCh:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cap iteratively flushes old but still referenced trie nodes until the total
|
// Cap iteratively flushes old but still referenced trie nodes until the total
|
||||||
// memory usage goes below the given threshold. The held pre-images accumulated
|
// memory usage goes below the given threshold. The held pre-images accumulated
|
||||||
// up to this point will be flushed in case the size exceeds the threshold.
|
// up to this point will be flushed in case the size exceeds the threshold.
|
||||||
Loading…
Reference in a new issue