From 5e4509a5436799e57e20f95ba7ae012c4b493b47 Mon Sep 17 00:00:00 2001 From: Aaron Buchwald Date: Thu, 11 Sep 2025 16:55:56 -0400 Subject: [PATCH 01/13] Generalize benchmark top level metrics def --- tests/reexecute/c/vm_reexecute_test.go | 28 ++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index 63b32eb2b80d..940a68859c51 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -82,6 +82,13 @@ var ( "state-sync-enabled": false }`, } + topLevelMetrics = []topLevelMetric{ + { + MetricName: "mgas/s", + Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, + Denominator: 1_000_000, + }, + } configNameArg string runnerNameArg string @@ -593,13 +600,26 @@ func parseCustomLabels(labelsStr string) (map[string]string, error) { return labels, nil } +type topLevelMetric struct { + MetricName string + Queries []string + Denominator float64 +} + func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { r := require.New(b) - gasUsed, err := getCounterMetricValue(registry, "avalanche_evm_eth_chain_block_gas_used_processed") - r.NoError(err) - mgasPerSecond := gasUsed / 1_000_000 / elapsed.Seconds() - b.ReportMetric(mgasPerSecond, "mgas/s") + for _, metric := range topLevelMetrics { + metricCounterVal := float64(0) + for _, query := range metric.Queries { + val, err := getCounterMetricValue(registry, query) + r.NoError(err, "failed to get counter value for metric %q from query %q", metric.MetricName, query) + metricCounterVal += val + } + + metricPerSecond := metricCounterVal / metric.Denominator / elapsed.Seconds() + b.ReportMetric(metricPerSecond, metric.MetricName) + } } func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { From a01ca08f3da23f45406b6aff2df6f5cc4392ba21 Mon Sep 17 00:00:00 2001 From: Aaron Buchwald Date: Fri, 12 Sep 2025 13:00:38 -0400 Subject: [PATCH 02/13] expand benchmark metrics and normalize in terms of mgas --- tests/reexecute/c/vm_reexecute_test.go | 130 ++++++++++++++++++++----- 1 file changed, 105 insertions(+), 25 deletions(-) diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index 940a68859c51..3f026379e36f 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -82,11 +82,79 @@ var ( "state-sync-enabled": false }`, } + denominatorMetric = topLevelMetric{ + MetricName: "mgas", + Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, + Denominator: 1_000_000, + } topLevelMetrics = []topLevelMetric{ { - MetricName: "mgas/s", - Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, - Denominator: 1_000_000, + MetricName: "content_validation", + Queries: []string{"avalanche_evm_eth_chain_block_validations_content"}, + Denominator: 1, + }, + { + MetricName: "state_init", + Queries: []string{ + "avalanche_evm_eth_chain_block_inits_state", + }, + Denominator: 1, + }, + { + MetricName: "execution", + Queries: []string{ + "avalanche_evm_eth_chain_block_executions", + }, + Denominator: 1, + }, + { + MetricName: "block_validation", + Queries: []string{ + "avalanche_evm_eth_chain_block_validations_state", + }, + Denominator: 1, + }, + { + MetricName: "trie_hash", + Queries: []string{ + "avalanche_evm_eth_chain_storage_hashes", + "avalanche_evm_eth_chain_account_hashes", + }, + Denominator: 1, + }, + { + MetricName: "trie_update", + Queries: []string{ + "avalanche_evm_eth_chain_account_updates", + "avalanche_evm_eth_chain_storage_updates", + }, + Denominator: 1, + }, + { + MetricName: "trie_read", + Queries: []string{ + "avalanche_evm_eth_chain_snapshot_account_reads", + "avalanche_evm_eth_chain_account_reads", + "avalanche_evm_eth_chain_snapshot_storage_reads", + "avalanche_evm_eth_chain_storage_reads", + }, + Denominator: 1, + }, + { + MetricName: "block_write", + Queries: []string{ + "avalanche_evm_eth_chain_block_writes", + }, + Denominator: 1, + }, + { + MetricName: "commit", + Queries: []string{ + "avalanche_evm_eth_chain_account_commits", + "avalanche_evm_eth_chain_storage_commits", + "avalanche_evm_eth_chain_snapshot_commits", + "avalanche_evm_eth_chain_triedb_commits", + }, }, } @@ -600,28 +668,6 @@ func parseCustomLabels(labelsStr string) (map[string]string, error) { return labels, nil } -type topLevelMetric struct { - MetricName string - Queries []string - Denominator float64 -} - -func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { - r := require.New(b) - - for _, metric := range topLevelMetrics { - metricCounterVal := float64(0) - for _, query := range metric.Queries { - val, err := getCounterMetricValue(registry, query) - r.NoError(err, "failed to get counter value for metric %q from query %q", metric.MetricName, query) - metricCounterVal += val - } - - metricPerSecond := metricCounterVal / metric.Denominator / elapsed.Seconds() - b.ReportMetric(metricPerSecond, metric.MetricName) - } -} - func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { metricFamilies, err := registry.Gather() if err != nil { @@ -636,3 +682,37 @@ func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, return 0, fmt.Errorf("metric %s not found", query) } + +type topLevelMetric struct { + MetricName string + Queries []string + Denominator float64 +} + +func calcMetric(tb testing.TB, m topLevelMetric, registry prometheus.Gatherer) float64 { + r := require.New(tb) + sum := float64(0) + for _, query := range m.Queries { + val, err := getCounterMetricValue(registry, query) + r.NoError(err, "failed to get counter value for metric %q query %q", m.MetricName, query) + sum += val + } + return sum / m.Denominator +} + +func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { + r := require.New(b) + + denominatorMetricVal := calcMetric(b, denominatorMetric, registry) + r.NotZero(denominatorMetricVal, "denominator metric %q has value 0", denominatorMetric.MetricName) + + denominatorPerSecond := denominatorMetricVal / elapsed.Seconds() + b.ReportMetric(denominatorPerSecond, fmt.Sprintf("%s/s", denominatorMetric.MetricName)) + + for _, metric := range topLevelMetrics { + counterVal := calcMetric(b, metric, registry) + counterVal /= denominatorMetricVal + + b.ReportMetric(counterVal, fmt.Sprintf("%s/%s", metric.MetricName, denominatorMetric.MetricName)) + } +} From b046a4b393ddcce3de7cffb664267da22c88d41a Mon Sep 17 00:00:00 2001 From: Aaron Buchwald Date: Fri, 12 Sep 2025 13:35:48 -0400 Subject: [PATCH 03/13] normalize extra metrics to gigagas --- tests/reexecute/c/metrics.go | 129 +++++++++++++++++++++++++ tests/reexecute/c/vm_reexecute_test.go | 124 ------------------------ 2 files changed, 129 insertions(+), 124 deletions(-) create mode 100644 tests/reexecute/c/metrics.go diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go new file mode 100644 index 000000000000..8bc95f075fd3 --- /dev/null +++ b/tests/reexecute/c/metrics.go @@ -0,0 +1,129 @@ +// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package vm + +import ( + "fmt" + "testing" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/stretchr/testify/require" +) + +var ( + gasMetric = topLevelMetric{ + Name: "gas", + Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, + } + topLevelMetrics = []topLevelMetric{ + { + Name: "content_validation", + Queries: []string{"avalanche_evm_eth_chain_block_validations_content"}, + }, + { + Name: "state_init", + Queries: []string{ + "avalanche_evm_eth_chain_block_inits_state", + }, + }, + { + Name: "execution", + Queries: []string{ + "avalanche_evm_eth_chain_block_executions", + }, + }, + { + Name: "block_validation", + Queries: []string{ + "avalanche_evm_eth_chain_block_validations_state", + }, + }, + { + Name: "trie_hash", + Queries: []string{ + "avalanche_evm_eth_chain_storage_hashes", + "avalanche_evm_eth_chain_account_hashes", + }, + }, + { + Name: "trie_update", + Queries: []string{ + "avalanche_evm_eth_chain_account_updates", + "avalanche_evm_eth_chain_storage_updates", + }, + }, + { + Name: "trie_read", + Queries: []string{ + "avalanche_evm_eth_chain_snapshot_account_reads", + "avalanche_evm_eth_chain_account_reads", + "avalanche_evm_eth_chain_snapshot_storage_reads", + "avalanche_evm_eth_chain_storage_reads", + }, + }, + { + Name: "block_write", + Queries: []string{ + "avalanche_evm_eth_chain_block_writes", + }, + }, + { + Name: "commit", + Queries: []string{ + "avalanche_evm_eth_chain_account_commits", + "avalanche_evm_eth_chain_storage_commits", + "avalanche_evm_eth_chain_snapshot_commits", + "avalanche_evm_eth_chain_triedb_commits", + }, + }, + } +) + +func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { + metricFamilies, err := registry.Gather() + if err != nil { + return 0, fmt.Errorf("failed to gather metrics: %w", err) + } + + for _, mf := range metricFamilies { + if mf.GetName() == query { + return mf.GetMetric()[0].Counter.GetValue(), nil + } + } + + return 0, fmt.Errorf("metric %s not found", query) +} + +type topLevelMetric struct { + Name string + Queries []string +} + +func calcMetric(tb testing.TB, m topLevelMetric, registry prometheus.Gatherer) float64 { + r := require.New(tb) + sum := float64(0) + for _, query := range m.Queries { + val, err := getCounterMetricValue(registry, query) + r.NoError(err, "failed to get counter value for metric %q query %q", m.Name, query) + sum += val + } + return sum +} + +func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { + r := require.New(b) + + totalGas := calcMetric(b, gasMetric, registry) + r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.Name) + + mgasPerSecond := totalGas / 1_000_000 / elapsed.Seconds() // mega + b.ReportMetric(mgasPerSecond, fmt.Sprintf("m%s/s", gasMetric.Name)) + + totalGGas := totalGas / 1_000_000_000 // giga + for _, metric := range topLevelMetrics { + counterVal := calcMetric(b, metric, registry) / (totalGGas) // metric / ggas + b.ReportMetric(counterVal, fmt.Sprintf("%s/g%s", metric.Name, gasMetric.Name)) + } +} diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index 3f026379e36f..d65076f60c72 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -82,81 +82,6 @@ var ( "state-sync-enabled": false }`, } - denominatorMetric = topLevelMetric{ - MetricName: "mgas", - Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, - Denominator: 1_000_000, - } - topLevelMetrics = []topLevelMetric{ - { - MetricName: "content_validation", - Queries: []string{"avalanche_evm_eth_chain_block_validations_content"}, - Denominator: 1, - }, - { - MetricName: "state_init", - Queries: []string{ - "avalanche_evm_eth_chain_block_inits_state", - }, - Denominator: 1, - }, - { - MetricName: "execution", - Queries: []string{ - "avalanche_evm_eth_chain_block_executions", - }, - Denominator: 1, - }, - { - MetricName: "block_validation", - Queries: []string{ - "avalanche_evm_eth_chain_block_validations_state", - }, - Denominator: 1, - }, - { - MetricName: "trie_hash", - Queries: []string{ - "avalanche_evm_eth_chain_storage_hashes", - "avalanche_evm_eth_chain_account_hashes", - }, - Denominator: 1, - }, - { - MetricName: "trie_update", - Queries: []string{ - "avalanche_evm_eth_chain_account_updates", - "avalanche_evm_eth_chain_storage_updates", - }, - Denominator: 1, - }, - { - MetricName: "trie_read", - Queries: []string{ - "avalanche_evm_eth_chain_snapshot_account_reads", - "avalanche_evm_eth_chain_account_reads", - "avalanche_evm_eth_chain_snapshot_storage_reads", - "avalanche_evm_eth_chain_storage_reads", - }, - Denominator: 1, - }, - { - MetricName: "block_write", - Queries: []string{ - "avalanche_evm_eth_chain_block_writes", - }, - Denominator: 1, - }, - { - MetricName: "commit", - Queries: []string{ - "avalanche_evm_eth_chain_account_commits", - "avalanche_evm_eth_chain_storage_commits", - "avalanche_evm_eth_chain_snapshot_commits", - "avalanche_evm_eth_chain_triedb_commits", - }, - }, - } configNameArg string runnerNameArg string @@ -667,52 +592,3 @@ func parseCustomLabels(labelsStr string) (map[string]string, error) { } return labels, nil } - -func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { - metricFamilies, err := registry.Gather() - if err != nil { - return 0, fmt.Errorf("failed to gather metrics: %w", err) - } - - for _, mf := range metricFamilies { - if mf.GetName() == query { - return mf.GetMetric()[0].Counter.GetValue(), nil - } - } - - return 0, fmt.Errorf("metric %s not found", query) -} - -type topLevelMetric struct { - MetricName string - Queries []string - Denominator float64 -} - -func calcMetric(tb testing.TB, m topLevelMetric, registry prometheus.Gatherer) float64 { - r := require.New(tb) - sum := float64(0) - for _, query := range m.Queries { - val, err := getCounterMetricValue(registry, query) - r.NoError(err, "failed to get counter value for metric %q query %q", m.MetricName, query) - sum += val - } - return sum / m.Denominator -} - -func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { - r := require.New(b) - - denominatorMetricVal := calcMetric(b, denominatorMetric, registry) - r.NotZero(denominatorMetricVal, "denominator metric %q has value 0", denominatorMetric.MetricName) - - denominatorPerSecond := denominatorMetricVal / elapsed.Seconds() - b.ReportMetric(denominatorPerSecond, fmt.Sprintf("%s/s", denominatorMetric.MetricName)) - - for _, metric := range topLevelMetrics { - counterVal := calcMetric(b, metric, registry) - counterVal /= denominatorMetricVal - - b.ReportMetric(counterVal, fmt.Sprintf("%s/%s", metric.MetricName, denominatorMetric.MetricName)) - } -} From dd307b7c3adba029eda80e8e496637aed902f12e Mon Sep 17 00:00:00 2001 From: Aaron Buchwald Date: Fri, 12 Sep 2025 14:05:12 -0400 Subject: [PATCH 04/13] Add s tracked/total --- tests/reexecute/c/metrics.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index 8bc95f075fd3..9f17f9642b7c 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -122,8 +122,15 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time b.ReportMetric(mgasPerSecond, fmt.Sprintf("m%s/s", gasMetric.Name)) totalGGas := totalGas / 1_000_000_000 // giga + + totalMSTrackedPerGGas := float64(0) for _, metric := range topLevelMetrics { - counterVal := calcMetric(b, metric, registry) / (totalGGas) // metric / ggas - b.ReportMetric(counterVal, fmt.Sprintf("%s/g%s", metric.Name, gasMetric.Name)) + metricValMS := calcMetric(b, metric, registry) / (totalGGas) // metric / ggas + totalMSTrackedPerGGas += metricValMS + b.ReportMetric(metricValMS, fmt.Sprintf("%s_ms/g%s", metric.Name, gasMetric.Name)) } + totalSTracked := totalMSTrackedPerGGas / 1000 + b.ReportMetric(totalSTracked, "s_tracked") + b.ReportMetric(elapsed.Seconds(), "s_total") + b.ReportMetric(totalSTracked/elapsed.Seconds(), "s_tracked/s_total") } From 240480703801d083e9cd6a14c25c3e3d00fd3c49 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Wed, 17 Sep 2025 17:35:26 -0400 Subject: [PATCH 05/13] feat: add metervm --- tests/reexecute/c/vm_reexecute_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index d65076f60c72..2d7fdb6c7048 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -41,6 +41,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/metervm" "github.com/ava-labs/avalanchego/vms/platformvm/warp" ) @@ -168,6 +169,9 @@ func benchmarkReexecuteRange( vmMultiGatherer := metrics.NewPrefixGatherer() r.NoError(prefixGatherer.Register("avalanche_evm", vmMultiGatherer)) + meterVMGatherer := metrics.NewPrefixGatherer() + r.NoError(prefixGatherer.Register("avalanche_meterchainvm", meterVMGatherer)) + // consensusRegistry includes the chain="C" label and the prefix "avalanche_snowman". // The consensus registry is passed to the executor to mimic a subset of consensus metrics. consensusRegistry := prometheus.NewRegistry() @@ -211,6 +215,7 @@ func benchmarkReexecuteRange( chainDataDir, configBytes, vmMultiGatherer, + meterVMGatherer, ) r.NoError(err) defer func() { @@ -241,7 +246,8 @@ func newMainnetCChainVM( vmAndSharedMemoryDB database.Database, chainDataDir string, configBytes []byte, - metricsGatherer metrics.MultiGatherer, + vmMultiGatherer metrics.MultiGatherer, + meterVMGatherer metrics.MultiGatherer, ) (block.ChainVM, error) { factory := factory.Factory{} vmIntf, err := factory.New(logging.NoLog{}) @@ -269,6 +275,13 @@ func newMainnetCChainVM( ids.Empty: constants.PrimaryNetworkID, } + meterVMRegistry, err := metrics.MakeAndRegister(meterVMGatherer, "C") + if err != nil { + return nil, fmt.Errorf("failed to create meterVM registry: %w", err) + } + + vm = metervm.NewBlockVM(vm, meterVMRegistry) + if err := vm.Initialize( ctx, &snow.Context{ @@ -286,7 +299,7 @@ func newMainnetCChainVM( Log: tests.NewDefaultLogger("mainnet-vm-reexecution"), SharedMemory: atomicMemory.NewSharedMemory(mainnetCChainID), BCLookup: ids.NewAliaser(), - Metrics: metricsGatherer, + Metrics: vmMultiGatherer, WarpSigner: warpSigner, From 8fea01db744ee5f08b8cabef9fb77841cd28bc63 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Thu, 18 Sep 2025 09:36:45 -0400 Subject: [PATCH 06/13] chore: add benchmark stats for metervm --- tests/reexecute/c/metrics.go | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index 9f17f9642b7c..97eda86f16ce 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -79,6 +79,20 @@ var ( }, }, } + meterVMMetrics = []topLevelMetric{ + { + Name: "avg_block_parse", + Queries: []string{"avalanche_meterchainvm_C_parse_block"}, + }, + { + Name: "avg_block_verify", + Queries: []string{"avalanche_meterchainvm_C_verify"}, + }, + { + Name: "avg_block_accept", + Queries: []string{"avalanche_meterchainvm_C_accept"}, + }, + } ) func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { @@ -96,6 +110,38 @@ func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, return 0, fmt.Errorf("metric %s not found", query) } +func getAveragerValue(registry prometheus.Gatherer, query string) (float64, error) { + metricFamilies, err := registry.Gather() + if err != nil { + return 0, fmt.Errorf("failed to gather metrics: %w", err) + } + + var ( + sumName = query + "_sum" + countName = query + "_count" + + sum float64 + count float64 + ) + + for _, mf := range metricFamilies { + name := mf.GetName() + switch name { + case sumName: + sum = mf.GetMetric()[0].Gauge.GetValue() + case countName: + count = mf.GetMetric()[0].Counter.GetValue() + default: + } + } + + if sum == 0 || count == 0 { + return 0, fmt.Errorf("failed to compute averager value for %s", query) + } + + return sum / count, nil +} + type topLevelMetric struct { Name string Queries []string @@ -129,6 +175,18 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time totalMSTrackedPerGGas += metricValMS b.ReportMetric(metricValMS, fmt.Sprintf("%s_ms/g%s", metric.Name, gasMetric.Name)) } + + for _, metric := range meterVMMetrics { + query := metric.Queries[0] + queryVal, err := getAveragerValue(registry, query) + r.NoError(err) + + // convert from ns to ms + queryVal /= 1_000_000 + + b.ReportMetric(queryVal, metric.Name+"_ms/block") + } + totalSTracked := totalMSTrackedPerGGas / 1000 b.ReportMetric(totalSTracked, "s_tracked") b.ReportMetric(elapsed.Seconds(), "s_total") From 893adbbd4912923faef32d06c066650b4e4f2e66 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 11:24:49 -0400 Subject: [PATCH 07/13] chore: simplify metrics --- tests/reexecute/c/metrics.go | 154 +++++++---------------------------- 1 file changed, 29 insertions(+), 125 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index 97eda86f16ce..abc2b8c66f68 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -14,83 +14,21 @@ import ( var ( gasMetric = topLevelMetric{ - Name: "gas", - Queries: []string{"avalanche_evm_eth_chain_block_gas_used_processed"}, - } - topLevelMetrics = []topLevelMetric{ - { - Name: "content_validation", - Queries: []string{"avalanche_evm_eth_chain_block_validations_content"}, - }, - { - Name: "state_init", - Queries: []string{ - "avalanche_evm_eth_chain_block_inits_state", - }, - }, - { - Name: "execution", - Queries: []string{ - "avalanche_evm_eth_chain_block_executions", - }, - }, - { - Name: "block_validation", - Queries: []string{ - "avalanche_evm_eth_chain_block_validations_state", - }, - }, - { - Name: "trie_hash", - Queries: []string{ - "avalanche_evm_eth_chain_storage_hashes", - "avalanche_evm_eth_chain_account_hashes", - }, - }, - { - Name: "trie_update", - Queries: []string{ - "avalanche_evm_eth_chain_account_updates", - "avalanche_evm_eth_chain_storage_updates", - }, - }, - { - Name: "trie_read", - Queries: []string{ - "avalanche_evm_eth_chain_snapshot_account_reads", - "avalanche_evm_eth_chain_account_reads", - "avalanche_evm_eth_chain_snapshot_storage_reads", - "avalanche_evm_eth_chain_storage_reads", - }, - }, - { - Name: "block_write", - Queries: []string{ - "avalanche_evm_eth_chain_block_writes", - }, - }, - { - Name: "commit", - Queries: []string{ - "avalanche_evm_eth_chain_account_commits", - "avalanche_evm_eth_chain_storage_commits", - "avalanche_evm_eth_chain_snapshot_commits", - "avalanche_evm_eth_chain_triedb_commits", - }, - }, + name: "gas", + query: "avalanche_evm_eth_chain_block_gas_used_processed", } meterVMMetrics = []topLevelMetric{ { - Name: "avg_block_parse", - Queries: []string{"avalanche_meterchainvm_C_parse_block"}, + name: "block_parse", + query: "avalanche_meterchainvm_C_parse_block_sum", }, { - Name: "avg_block_verify", - Queries: []string{"avalanche_meterchainvm_C_verify"}, + name: "block_verify", + query: "avalanche_meterchainvm_C_verify_sum", }, { - Name: "avg_block_accept", - Queries: []string{"avalanche_meterchainvm_C_accept"}, + name: "block_accept", + query: "avalanche_meterchainvm_C_accept_sum", }, } ) @@ -110,85 +48,51 @@ func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, return 0, fmt.Errorf("metric %s not found", query) } -func getAveragerValue(registry prometheus.Gatherer, query string) (float64, error) { +func getGaugeMetricValue(registry prometheus.Gatherer, query string) (float64, error) { metricFamilies, err := registry.Gather() if err != nil { return 0, fmt.Errorf("failed to gather metrics: %w", err) } - var ( - sumName = query + "_sum" - countName = query + "_count" - - sum float64 - count float64 - ) - for _, mf := range metricFamilies { - name := mf.GetName() - switch name { - case sumName: - sum = mf.GetMetric()[0].Gauge.GetValue() - case countName: - count = mf.GetMetric()[0].Counter.GetValue() - default: + if mf.GetName() == query { + return mf.GetMetric()[0].Gauge.GetValue(), nil } } - if sum == 0 || count == 0 { - return 0, fmt.Errorf("failed to compute averager value for %s", query) - } - - return sum / count, nil + return 0, fmt.Errorf("metric %s not found", query) } type topLevelMetric struct { - Name string - Queries []string -} - -func calcMetric(tb testing.TB, m topLevelMetric, registry prometheus.Gatherer) float64 { - r := require.New(tb) - sum := float64(0) - for _, query := range m.Queries { - val, err := getCounterMetricValue(registry, query) - r.NoError(err, "failed to get counter value for metric %q query %q", m.Name, query) - sum += val - } - return sum + name string + query string } func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { r := require.New(b) - totalGas := calcMetric(b, gasMetric, registry) - r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.Name) + totalGas, err := getCounterMetricValue(registry, gasMetric.query) + r.NoError(err) + r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.name) - mgasPerSecond := totalGas / 1_000_000 / elapsed.Seconds() // mega - b.ReportMetric(mgasPerSecond, fmt.Sprintf("m%s/s", gasMetric.Name)) + var ( + gGas float64 = 1_000_000_000 + nsPerMs float64 = 1_000_000 + ) - totalGGas := totalGas / 1_000_000_000 // giga + totalGGas := totalGas / gGas + msPerGGas := (float64(elapsed) / nsPerMs) / totalGGas + b.ReportMetric(msPerGGas, "ms/gGas") totalMSTrackedPerGGas := float64(0) - for _, metric := range topLevelMetrics { - metricValMS := calcMetric(b, metric, registry) / (totalGGas) // metric / ggas - totalMSTrackedPerGGas += metricValMS - b.ReportMetric(metricValMS, fmt.Sprintf("%s_ms/g%s", metric.Name, gasMetric.Name)) - } - for _, metric := range meterVMMetrics { - query := metric.Queries[0] - queryVal, err := getAveragerValue(registry, query) + metricVal, err := getGaugeMetricValue(registry, metric.query) r.NoError(err) - // convert from ns to ms - queryVal /= 1_000_000 - - b.ReportMetric(queryVal, metric.Name+"_ms/block") + metricValMS := (metricVal / nsPerMs) / totalGGas + totalMSTrackedPerGGas += metricValMS + b.ReportMetric(metricValMS, metric.name+"_ms/gGas") } - totalSTracked := totalMSTrackedPerGGas / 1000 - b.ReportMetric(totalSTracked, "s_tracked") - b.ReportMetric(elapsed.Seconds(), "s_total") - b.ReportMetric(totalSTracked/elapsed.Seconds(), "s_tracked/s_total") + b.ReportMetric(totalMSTrackedPerGGas, "tracked_ms/gGas") } From 25dbab1ebed64b640631df4a666f1c4e369e719d Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 11:53:36 -0400 Subject: [PATCH 08/13] chore: add back mGas/s --- tests/reexecute/c/metrics.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index abc2b8c66f68..c3a0cc8d1cea 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -76,10 +76,14 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.name) var ( + mGas float64 = 1_000_000 gGas float64 = 1_000_000_000 nsPerMs float64 = 1_000_000 ) + mGasPerSecond := (totalGas / mGas) / elapsed.Seconds() + b.ReportMetric(mGasPerSecond, "mGas/s") + totalGGas := totalGas / gGas msPerGGas := (float64(elapsed) / nsPerMs) / totalGGas b.ReportMetric(msPerGGas, "ms/gGas") From 6345adde0f4f1da995aa7544a6364763aa0ba015 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 12:03:36 -0400 Subject: [PATCH 09/13] chore: fully formed registry --- tests/reexecute/c/vm_reexecute_test.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index 2d7fdb6c7048..2e4ddea23b75 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -169,8 +169,8 @@ func benchmarkReexecuteRange( vmMultiGatherer := metrics.NewPrefixGatherer() r.NoError(prefixGatherer.Register("avalanche_evm", vmMultiGatherer)) - meterVMGatherer := metrics.NewPrefixGatherer() - r.NoError(prefixGatherer.Register("avalanche_meterchainvm", meterVMGatherer)) + meterVMRegistry := prometheus.NewRegistry() + r.NoError(prefixGatherer.Register("avalanche_meterchainvm_C", meterVMRegistry)) // consensusRegistry includes the chain="C" label and the prefix "avalanche_snowman". // The consensus registry is passed to the executor to mimic a subset of consensus metrics. @@ -215,7 +215,7 @@ func benchmarkReexecuteRange( chainDataDir, configBytes, vmMultiGatherer, - meterVMGatherer, + meterVMRegistry, ) r.NoError(err) defer func() { @@ -247,7 +247,7 @@ func newMainnetCChainVM( chainDataDir string, configBytes []byte, vmMultiGatherer metrics.MultiGatherer, - meterVMGatherer metrics.MultiGatherer, + meterVMRegistry prometheus.Registerer, ) (block.ChainVM, error) { factory := factory.Factory{} vmIntf, err := factory.New(logging.NoLog{}) @@ -275,11 +275,6 @@ func newMainnetCChainVM( ids.Empty: constants.PrimaryNetworkID, } - meterVMRegistry, err := metrics.MakeAndRegister(meterVMGatherer, "C") - if err != nil { - return nil, fmt.Errorf("failed to create meterVM registry: %w", err) - } - vm = metervm.NewBlockVM(vm, meterVMRegistry) if err := vm.Initialize( From 63899f12a5633d71c614d88326a52dcdd9743848 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 13:29:14 -0400 Subject: [PATCH 10/13] chore: add metric kind --- tests/reexecute/c/metrics.go | 47 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index c3a0cc8d1cea..d0c65afb7eb8 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -12,51 +12,57 @@ import ( "github.com/stretchr/testify/require" ) +type metricKind uint + +const ( + counter metricKind = iota + 1 + gauge +) + var ( gasMetric = topLevelMetric{ name: "gas", query: "avalanche_evm_eth_chain_block_gas_used_processed", + kind: counter, } meterVMMetrics = []topLevelMetric{ { name: "block_parse", query: "avalanche_meterchainvm_C_parse_block_sum", + kind: gauge, }, { name: "block_verify", query: "avalanche_meterchainvm_C_verify_sum", + kind: gauge, }, { name: "block_accept", query: "avalanche_meterchainvm_C_accept_sum", + kind: gauge, }, } ) -func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) { - metricFamilies, err := registry.Gather() - if err != nil { - return 0, fmt.Errorf("failed to gather metrics: %w", err) - } - - for _, mf := range metricFamilies { - if mf.GetName() == query { - return mf.GetMetric()[0].Counter.GetValue(), nil - } - } - - return 0, fmt.Errorf("metric %s not found", query) -} - -func getGaugeMetricValue(registry prometheus.Gatherer, query string) (float64, error) { +func getMetricValue(registry prometheus.Gatherer, metric topLevelMetric) (float64, error) { metricFamilies, err := registry.Gather() if err != nil { return 0, fmt.Errorf("failed to gather metrics: %w", err) } + query := metric.query for _, mf := range metricFamilies { - if mf.GetName() == query { - return mf.GetMetric()[0].Gauge.GetValue(), nil + switch metric.kind { + case counter: + if mf.GetName() == query { + return mf.GetMetric()[0].Counter.GetValue(), nil + } + case gauge: + if mf.GetName() == query { + return mf.GetMetric()[0].Gauge.GetValue(), nil + } + default: + return 0, fmt.Errorf("metric type unknown: %d", metric.kind) } } @@ -66,12 +72,13 @@ func getGaugeMetricValue(registry prometheus.Gatherer, query string) (float64, e type topLevelMetric struct { name string query string + kind metricKind } func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) { r := require.New(b) - totalGas, err := getCounterMetricValue(registry, gasMetric.query) + totalGas, err := getMetricValue(registry, gasMetric) r.NoError(err) r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.name) @@ -90,7 +97,7 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time totalMSTrackedPerGGas := float64(0) for _, metric := range meterVMMetrics { - metricVal, err := getGaugeMetricValue(registry, metric.query) + metricVal, err := getMetricValue(registry, metric) r.NoError(err) metricValMS := (metricVal / nsPerMs) / totalGGas From eb87a254e7627dc69638d3cfdc5b62da5f90b8a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 13:39:40 -0400 Subject: [PATCH 11/13] chore: revert usage of camel case --- tests/reexecute/c/metrics.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index d0c65afb7eb8..ca3e42e1d1f5 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -83,17 +83,17 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.name) var ( - mGas float64 = 1_000_000 - gGas float64 = 1_000_000_000 + mgas float64 = 1_000_000 + ggas float64 = 1_000_000_000 nsPerMs float64 = 1_000_000 ) - mGasPerSecond := (totalGas / mGas) / elapsed.Seconds() - b.ReportMetric(mGasPerSecond, "mGas/s") + mgasPerSecond := (totalGas / mgas) / elapsed.Seconds() + b.ReportMetric(mgasPerSecond, "mgas/s") - totalGGas := totalGas / gGas + totalGGas := totalGas / ggas msPerGGas := (float64(elapsed) / nsPerMs) / totalGGas - b.ReportMetric(msPerGGas, "ms/gGas") + b.ReportMetric(msPerGGas, "ms/ggas") totalMSTrackedPerGGas := float64(0) for _, metric := range meterVMMetrics { @@ -102,8 +102,8 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time metricValMS := (metricVal / nsPerMs) / totalGGas totalMSTrackedPerGGas += metricValMS - b.ReportMetric(metricValMS, metric.name+"_ms/gGas") + b.ReportMetric(metricValMS, metric.name+"_ms/ggas") } - b.ReportMetric(totalMSTrackedPerGGas, "tracked_ms/gGas") + b.ReportMetric(totalMSTrackedPerGGas, "tracked_ms/ggas") } From 23a47e31defaaaf76eede0c1301e27688c79b7d0 Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 14:05:37 -0400 Subject: [PATCH 12/13] chore: rename metervm prefix --- tests/reexecute/c/metrics.go | 6 +++--- tests/reexecute/c/vm_reexecute_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index ca3e42e1d1f5..2bbc0f6a111c 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -28,17 +28,17 @@ var ( meterVMMetrics = []topLevelMetric{ { name: "block_parse", - query: "avalanche_meterchainvm_C_parse_block_sum", + query: "avalanche_meterchainvm_parse_block_sum", kind: gauge, }, { name: "block_verify", - query: "avalanche_meterchainvm_C_verify_sum", + query: "avalanche_meterchainvm_verify_sum", kind: gauge, }, { name: "block_accept", - query: "avalanche_meterchainvm_C_accept_sum", + query: "avalanche_meterchainvm_accept_sum", kind: gauge, }, } diff --git a/tests/reexecute/c/vm_reexecute_test.go b/tests/reexecute/c/vm_reexecute_test.go index 2e4ddea23b75..46044f5f6a33 100644 --- a/tests/reexecute/c/vm_reexecute_test.go +++ b/tests/reexecute/c/vm_reexecute_test.go @@ -170,7 +170,7 @@ func benchmarkReexecuteRange( r.NoError(prefixGatherer.Register("avalanche_evm", vmMultiGatherer)) meterVMRegistry := prometheus.NewRegistry() - r.NoError(prefixGatherer.Register("avalanche_meterchainvm_C", meterVMRegistry)) + r.NoError(prefixGatherer.Register("avalanche_meterchainvm", meterVMRegistry)) // consensusRegistry includes the chain="C" label and the prefix "avalanche_snowman". // The consensus registry is passed to the executor to mimic a subset of consensus metrics. From cbc62981cffa6d8941cbb457ef63dbd9fd03f0ca Mon Sep 17 00:00:00 2001 From: Rodrigo Villar Date: Tue, 30 Sep 2025 14:46:39 -0400 Subject: [PATCH 13/13] chore: remove totalMSTrackedPerGGas --- tests/reexecute/c/metrics.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/reexecute/c/metrics.go b/tests/reexecute/c/metrics.go index 2bbc0f6a111c..94906761f152 100644 --- a/tests/reexecute/c/metrics.go +++ b/tests/reexecute/c/metrics.go @@ -95,15 +95,11 @@ func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time msPerGGas := (float64(elapsed) / nsPerMs) / totalGGas b.ReportMetric(msPerGGas, "ms/ggas") - totalMSTrackedPerGGas := float64(0) for _, metric := range meterVMMetrics { metricVal, err := getMetricValue(registry, metric) r.NoError(err) metricValMS := (metricVal / nsPerMs) / totalGGas - totalMSTrackedPerGGas += metricValMS b.ReportMetric(metricValMS, metric.name+"_ms/ggas") } - - b.ReportMetric(totalMSTrackedPerGGas, "tracked_ms/ggas") }