diff --git a/README.md b/README.md index 7bd9ecfdeec4..5dfd3ed7d7f9 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,11 @@ $ geth --help --miner.extradata value Block extra data set by the miner (default = client version) + + METRICS + + --metrics.builder value (default: false) + Enable builder metrics collection and reporting ``` This will start `geth` in snap-sync mode with a DB memory allowance of 1GB, as the diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 96999075a316..62af70380571 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -81,6 +81,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`, utils.CacheGCFlag, utils.MetricsEnabledFlag, utils.MetricsEnabledExpensiveFlag, + utils.MetricsEnabledBuilderFlag, utils.MetricsHTTPFlag, utils.MetricsPortFlag, utils.MetricsEnableInfluxDBFlag, diff --git a/cmd/geth/config.go b/cmd/geth/config.go index eda9295d2ad4..e161a2da2476 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -235,6 +235,9 @@ func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) { if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) { cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name) } + if ctx.IsSet(utils.MetricsEnabledBuilderFlag.Name) { + cfg.Metrics.EnabledBuilder = ctx.Bool(utils.MetricsEnabledBuilderFlag.Name) + } if ctx.IsSet(utils.MetricsHTTPFlag.Name) { cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name) } diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 763b9e4570e0..84b85bff7ffe 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -207,6 +207,7 @@ var ( metricsFlags = []cli.Flag{ utils.MetricsEnabledFlag, utils.MetricsEnabledExpensiveFlag, + utils.MetricsEnabledBuilderFlag, utils.MetricsHTTPFlag, utils.MetricsPortFlag, utils.MetricsEnableInfluxDBFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index bd40ceeb0f51..d968ad19fe22 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1036,6 +1036,12 @@ var ( Usage: "Enable expensive metrics collection and reporting", Category: flags.MetricsCategory, } + // Builder metrics flag + MetricsEnabledBuilderFlag = &cli.BoolFlag{ + Name: "metrics.builder", + Usage: "Enable builder metrics collection and reporting", + Category: flags.MetricsCategory, + } // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. // Since the pprof service enables sensitive/vulnerable behavior, this allows a user diff --git a/core/state/statedb.go b/core/state/statedb.go index 3d8fd15bbd25..33856ffeaacd 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -795,6 +795,11 @@ func (s *StateDB) Copy() *StateDB { state.snapStorage[k] = temp } } + + if metrics.EnabledBuilder { + stateCopyMeter.Mark(1) + } + return state } @@ -803,6 +808,11 @@ func (s *StateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()}) + + if metrics.EnabledBuilder { + stateSnapshotMeter.Mark(1) + } + return id } diff --git a/metrics/config.go b/metrics/config.go index 2eb09fb48a33..f0e5a7be2b2f 100644 --- a/metrics/config.go +++ b/metrics/config.go @@ -20,6 +20,7 @@ package metrics type Config struct { Enabled bool `toml:",omitempty"` EnabledExpensive bool `toml:",omitempty"` + EnabledBuilder bool `toml:",omitempty"` HTTP string `toml:",omitempty"` Port int `toml:",omitempty"` EnableInfluxDB bool `toml:",omitempty"` @@ -39,6 +40,7 @@ type Config struct { var DefaultConfig = Config{ Enabled: false, EnabledExpensive: false, + EnabledBuilder: false, HTTP: "127.0.0.1", Port: 6060, EnableInfluxDB: false, diff --git a/metrics/metrics.go b/metrics/metrics.go index ff7196b56494..23a3ff0318d9 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -27,12 +27,18 @@ var Enabled = false // for health monitoring and debug metrics that might impact runtime performance. var EnabledExpensive = false +// EnabledBuilder is a flag meant to collect metrics and performance of the builder +var EnabledBuilder = false + // enablerFlags is the CLI flag names to use to enable metrics collections. var enablerFlags = []string{"metrics"} // expensiveEnablerFlags is the CLI flag names to use to enable metrics collections. var expensiveEnablerFlags = []string{"metrics.expensive"} +// builderEnablerFlags is the CLI flag names to use to enable metrics collections. +var builderEnablerFlags = []string{"metrics.builder"} + // Init enables or disables the metrics system. Since we need this to run before // any other code gets to create meters and timers, we'll actually do an ugly hack // and peek into the command line args for the metrics flag. @@ -52,6 +58,14 @@ func init() { EnabledExpensive = true } } + + for _, enabler := range builderEnablerFlags { + if !EnabledBuilder && flag == enabler { + log.Info("Enabling builder metrics collection") + EnabledBuilder = true + break + } + } } } diff --git a/miner/metrics.go b/miner/metrics.go new file mode 100644 index 000000000000..48d18eba64d7 --- /dev/null +++ b/miner/metrics.go @@ -0,0 +1,26 @@ +package miner + +import ( + "github.com/ethereum/go-ethereum/metrics" +) + +var ( + blockProfitHistogram = metrics.NewRegisteredHistogram("miner/block/profit", nil, metrics.NewExpDecaySample(1028, 0.015)) + bundleTxNumHistogram = metrics.NewRegisteredHistogram("miner/bundle/txnum", nil, metrics.NewExpDecaySample(1028, 0.015)) + blockProfitGauge = metrics.NewRegisteredGauge("miner/block/profit/gauge", nil) + culmulativeProfitGauge = metrics.NewRegisteredGauge("miner/block/profit/culmulative", nil) + + buildBlockTimer = metrics.NewRegisteredTimer("miner/block/build", nil) + mergeAlgoTimer = metrics.NewRegisteredTimer("miner/block/merge", nil) + blockBundleSimulationTimer = metrics.NewRegisteredTimer("miner/block/simulate", nil) + successfulBundleSimulationTimer = metrics.NewRegisteredTimer("miner/bundle/simulate/success", nil) + failedBundleSimulationTimer = metrics.NewRegisteredTimer("miner/bundle/simulate/failed", nil) + + + simulationMeter = metrics.NewRegisteredMeter("miner/block/simulation", nil) + simulationCommittedMeter = metrics.NewRegisteredMeter("miner/block/simulation/committed", nil) + simulationRevertedMeter = metrics.NewRegisteredMeter("miner/block/simulation/reverted", nil) + + gasUsedGauge = metrics.NewRegisteredGauge("miner/block/gasused", nil) + transactionNumGauge = metrics.NewRegisteredGauge("miner/block/txnum", nil) +) diff --git a/miner/worker.go b/miner/worker.go index 2f41144901c1..2a98472869d1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" ) @@ -1396,7 +1397,11 @@ func (w *worker) fillTransactionsAlgoWorker(interrupt *int32, env *environment) } builder := newGreedyBuilder(w.chain, w.chainConfig, w.blockList, env, interrupt) + start := time.Now() newEnv, blockBundles := builder.buildBlock(bundlesToConsider, pending) + if metrics.EnabledBuilder { + mergeAlgoTimer.Update(time.Since(start)) + } *env = *newEnv return nil, blockBundles, bundlesToConsider @@ -1679,17 +1684,37 @@ func (w *worker) simulateBundles(env *environment, bundles []types.MevBundle, pe wg.Add(1) go func(idx int, bundle types.MevBundle, state *state.StateDB) { defer wg.Done() + + start := time.Now() + if metrics.EnabledBuilder { + bundleTxNumHistogram.Update(int64(len(bundle.Txs))) + } + if len(bundle.Txs) == 0 { return } gasPool := new(core.GasPool).AddGas(env.header.GasLimit) simmed, err := w.computeBundleGas(env, bundle, state, gasPool, pendingTxs, 0) + if metrics.EnabledBuilder { + simulationMeter.Mark(1) + } + if err != nil { + if metrics.EnabledBuilder { + simulationRevertedMeter.Mark(1) + failedBundleSimulationTimer.UpdateSince(start) + } + log.Trace("Error computing gas for a bundle", "error", err) return } simResult[idx] = &simmed + + if metrics.EnabledBuilder { + simulationCommittedMeter.Mark(1) + successfulBundleSimulationTimer.UpdateSince(start) + } }(i, bundle, env.state.Copy()) } @@ -1705,6 +1730,9 @@ func (w *worker) simulateBundles(env *environment, bundles []types.MevBundle, pe } log.Debug("Simulated bundles", "block", env.header.Number, "allBundles", len(bundles), "okBundles", len(simulatedBundles), "time", time.Since(start)) + if metrics.EnabledBuilder { + blockBundleSimulationTimer.Update(time.Since(start)) + } return simulatedBundles, nil }