mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
state: debug_stateSize to retrieve the latest state size
This commit is contained in:
parent
c99f43e41a
commit
70cd55dcd2
7 changed files with 59 additions and 47 deletions
|
|
@ -108,7 +108,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
|||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
utils.MetricsStateSizeFlag,
|
||||
utils.StateSizeTrackingFlag,
|
||||
utils.TxLookupLimitFlag,
|
||||
utils.VMTraceFlag,
|
||||
utils.VMTraceJsonConfigFlag,
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ var (
|
|||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
utils.MetricsStateSizeFlag,
|
||||
utils.StateSizeTrackingFlag,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -628,6 +628,12 @@ var (
|
|||
TakesFile: true,
|
||||
Category: flags.MiscCategory,
|
||||
}
|
||||
StateSizeTrackingFlag = &cli.BoolFlag{
|
||||
Name: "state-size-tracking",
|
||||
Usage: "Enable state size tracking",
|
||||
Value: ethconfig.Defaults.EnableStateSizeTracking,
|
||||
Category: flags.MiscCategory,
|
||||
}
|
||||
|
||||
// RPC settings
|
||||
IPCDisabledFlag = &cli.BoolFlag{
|
||||
|
|
@ -966,13 +972,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
||||
Category: flags.MetricsCategory,
|
||||
}
|
||||
|
||||
MetricsStateSizeFlag = &cli.BoolFlag{
|
||||
Name: "metrics.statesize",
|
||||
Usage: "Enable state size tracking for metrics collection",
|
||||
Value: ethconfig.Defaults.EnableStateSizeTracking,
|
||||
Category: flags.MetricsCategory,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1734,7 +1733,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
}
|
||||
}
|
||||
|
||||
if ctx.Bool(MetricsEnabledFlag.Name) && ctx.Bool(MetricsStateSizeFlag.Name) {
|
||||
if ctx.Bool(StateSizeTrackingFlag.Name) {
|
||||
log.Info("Enabling state size metrics")
|
||||
cfg.EnableStateSizeTracking = true
|
||||
}
|
||||
|
|
@ -2221,8 +2220,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||
// - DATADIR/triedb/verkle.journal
|
||||
TrieJournalDirectory: stack.ResolvePath("triedb"),
|
||||
|
||||
// Enable state size tracking if metrics and state size metrics are both enabled
|
||||
EnableStateSizeTracking: ctx.Bool(MetricsEnabledFlag.Name) && ctx.Bool(MetricsStateSizeFlag.Name),
|
||||
// Enable state size tracking if enabled
|
||||
EnableStateSizeTracking: ctx.Bool(StateSizeTrackingFlag.Name),
|
||||
}
|
||||
if options.ArchiveMode && !options.Preimages {
|
||||
options.Preimages = true
|
||||
|
|
|
|||
|
|
@ -2814,3 +2814,8 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
|
|||
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
|
||||
return time.Duration(bc.flushInterval.Load())
|
||||
}
|
||||
|
||||
// StateSizer returns the state size tracker, or nil if it's not initialized
|
||||
func (bc *BlockChain) StateSizer() *state.SizeTracker {
|
||||
return bc.stateSizer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
|
@ -40,25 +38,10 @@ const (
|
|||
statEvictThreshold = 128 // the depth of statistic to be preserved
|
||||
)
|
||||
|
||||
// Metrics for uploading the state statistics.
|
||||
var (
|
||||
blockInfoGauge = metrics.NewRegisteredGaugeInfo("state/size/block", nil)
|
||||
accountsGauge = metrics.NewRegisteredGauge("state/size/account/count", nil)
|
||||
accountBytesGauge = metrics.NewRegisteredGauge("state/size/account/bytes", nil)
|
||||
storagesGauge = metrics.NewRegisteredGauge("state/size/storage/count", nil)
|
||||
storageBytesGauge = metrics.NewRegisteredGauge("state/size/storage/bytes", nil)
|
||||
accountTrienodesGauge = metrics.NewRegisteredGauge("state/size/trienode/account/count", nil)
|
||||
accountTrienodeBytesGauge = metrics.NewRegisteredGauge("state/size/trienode/account/bytes", nil)
|
||||
storageTrienodesGauge = metrics.NewRegisteredGauge("state/size/trienode/storage/count", nil)
|
||||
storageTrienodeBytesGauge = metrics.NewRegisteredGauge("state/size/trienode/storage/bytes", nil)
|
||||
contractCodesGauge = metrics.NewRegisteredGauge("state/size/contractcode/count", nil)
|
||||
contractCodeBytesGauge = metrics.NewRegisteredGauge("state/size/contractcode/bytes", nil)
|
||||
)
|
||||
|
||||
// Database key scheme for states.
|
||||
var (
|
||||
accountKeySize = int64(len(rawdb.SnapshotAccountPrefix) + common.HashLength)
|
||||
storageKeySize = int64(len(rawdb.SnapshotStoragePrefix) + common.HashLength + common.HashLength)
|
||||
storageKeySize = int64(len(rawdb.SnapshotStoragePrefix) + common.HashLength*2)
|
||||
accountTrienodePrefixSize = int64(len(rawdb.TrieNodeAccountPrefix))
|
||||
storageTrienodePrefixSize = int64(len(rawdb.TrieNodeStoragePrefix) + common.HashLength)
|
||||
codeKeySize = int64(len(rawdb.CodePrefix) + common.HashLength)
|
||||
|
|
@ -246,6 +229,9 @@ type SizeTracker struct {
|
|||
abort chan struct{}
|
||||
aborted chan struct{}
|
||||
updateCh chan *stateUpdate
|
||||
|
||||
mu sync.RWMutex
|
||||
latestStats *SizeStats
|
||||
}
|
||||
|
||||
// NewSizeTracker creates a new state size tracker and starts it automatically
|
||||
|
|
@ -313,7 +299,12 @@ func (t *SizeTracker) run() {
|
|||
}
|
||||
stat := base.add(diff)
|
||||
stats[u.root] = stat
|
||||
t.upload(stat)
|
||||
log.Info("Update state size", "number", stat.BlockNumber, "root", stat.StateRoot, "stat", stat)
|
||||
|
||||
// Update latest stats
|
||||
t.mu.Lock()
|
||||
t.latestStats = &stat
|
||||
t.mu.Unlock()
|
||||
|
||||
heap.Push(&h, stats[u.root])
|
||||
for u.blockNumber-h[0].BlockNumber > statEvictThreshold {
|
||||
|
|
@ -415,6 +406,13 @@ wait:
|
|||
if err := apply(result.root, result.stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set initial latest stats
|
||||
stats[result.root] = result.stat
|
||||
t.mu.Lock()
|
||||
t.latestStats = &result.stat
|
||||
t.mu.Unlock()
|
||||
|
||||
log.Info("Measured persistent state size", "root", result.root, "number", result.blockNumber, "stat", result.stat, "elapsed", common.PrettyDuration(result.elapsed))
|
||||
return stats, nil
|
||||
|
||||
|
|
@ -600,20 +598,9 @@ func (t *SizeTracker) iterateTableParallel(closed chan struct{}, prefix []byte,
|
|||
return totalCount, totalBytes, nil
|
||||
}
|
||||
|
||||
func (t *SizeTracker) upload(stats SizeStats) {
|
||||
log.Debug("Uploading state size", "number", stats.BlockNumber, "root", stats.StateRoot, "stat", stats)
|
||||
blockInfoGauge.Update(metrics.GaugeInfoValue{
|
||||
"number": hexutil.Uint64(stats.BlockNumber).String(),
|
||||
"hash": stats.StateRoot.Hex(),
|
||||
})
|
||||
accountsGauge.Update(stats.Accounts)
|
||||
accountBytesGauge.Update(stats.AccountBytes)
|
||||
storagesGauge.Update(stats.Storages)
|
||||
storageBytesGauge.Update(stats.StorageBytes)
|
||||
accountTrienodesGauge.Update(stats.AccountTrienodes)
|
||||
accountTrienodeBytesGauge.Update(stats.AccountTrienodeBytes)
|
||||
storageTrienodesGauge.Update(stats.StorageTrienodes)
|
||||
storageTrienodeBytesGauge.Update(stats.StorageTrienodeBytes)
|
||||
contractCodesGauge.Update(stats.ContractCodes)
|
||||
contractCodeBytesGauge.Update(stats.ContractCodeBytes)
|
||||
// GetLatestStats returns the latest state size statistics, or nil if not available
|
||||
func (t *SizeTracker) GetLatestStats() *SizeStats {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
return t.latestStats
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,3 +443,19 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
|
|||
}
|
||||
return api.eth.blockchain.GetTrieFlushInterval().String(), nil
|
||||
}
|
||||
|
||||
// StateSize returns the current state size statistics from the state size tracker.
|
||||
// Returns an error if the state size tracker is not initialized or if stats are not ready.
|
||||
func (api *DebugAPI) StateSize() (*state.SizeStats, error) {
|
||||
sizer := api.eth.blockchain.StateSizer()
|
||||
if sizer == nil {
|
||||
return nil, errors.New("state size tracker is not enabled")
|
||||
}
|
||||
|
||||
stats := sizer.GetLatestStats()
|
||||
if stats == nil {
|
||||
return nil, errors.New("state size statistics are not ready yet")
|
||||
}
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,6 +468,11 @@ web3._extend({
|
|||
call: 'debug_sync',
|
||||
params: 1
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'stateSize',
|
||||
call: 'debug_stateSize',
|
||||
params: 0,
|
||||
}),
|
||||
],
|
||||
properties: []
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue