Skip to content

Commit

Permalink
op-challenger: Add metric to report memory used in the cannon VM (#11350
Browse files Browse the repository at this point in the history
)

* op-challenger: Add metric to report memory used in the cannon VM

* op-challenger: Remove config override.
  • Loading branch information
ajsutton authored Aug 5, 2024
1 parent df33bf1 commit f940301
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 9 deletions.
9 changes: 6 additions & 3 deletions cannon/mipsevm/debug.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package mipsevm

import "github.com/ethereum/go-ethereum/common/hexutil"

type DebugInfo struct {
Pages int `json:"pages"`
NumPreimageRequests int `json:"num_preimage_requests"`
TotalPreimageSize int `json:"total_preimage_size"`
Pages int `json:"pages"`
MemoryUsed hexutil.Uint64 `json:"memory_used"`
NumPreimageRequests int `json:"num_preimage_requests"`
TotalPreimageSize int `json:"total_preimage_size"`
}
6 changes: 5 additions & 1 deletion cannon/mipsevm/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,12 @@ func (m *Memory) ReadMemoryRange(addr uint32, count uint32) io.Reader {
return &memReader{m: m, addr: addr, count: count}
}

func (m *Memory) UsageRaw() uint64 {
return uint64(len(m.pages)) * PageSize
}

func (m *Memory) Usage() string {
total := uint64(len(m.pages)) * PageSize
total := m.UsageRaw()
const unit = 1024
if total < unit {
return fmt.Sprintf("%d B", total)
Expand Down
2 changes: 2 additions & 0 deletions cannon/mipsevm/multithreaded/instrumented.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package multithreaded
import (
"io"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"

"github.com/ethereum-optimism/optimism/cannon/mipsevm"
Expand Down Expand Up @@ -106,6 +107,7 @@ func (m *InstrumentedState) GetState() mipsevm.FPVMState {
func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo {
return &mipsevm.DebugInfo{
Pages: m.state.Memory.PageCount(),
MemoryUsed: hexutil.Uint64(m.state.Memory.UsageRaw()),
NumPreimageRequests: m.preimageOracle.NumPreimageRequests(),
TotalPreimageSize: m.preimageOracle.TotalPreimageSize(),
}
Expand Down
2 changes: 2 additions & 0 deletions cannon/mipsevm/singlethreaded/instrumented.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common/hexutil"
)

type InstrumentedState struct {
Expand Down Expand Up @@ -109,6 +110,7 @@ func (m *InstrumentedState) GetState() mipsevm.FPVMState {
func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo {
return &mipsevm.DebugInfo{
Pages: m.state.Memory.PageCount(),
MemoryUsed: hexutil.Uint64(m.state.Memory.UsageRaw()),
NumPreimageRequests: m.preimageOracle.NumPreimageRequests(),
TotalPreimageSize: m.preimageOracle.TotalPreimageSize(),
}
Expand Down
1 change: 1 addition & 0 deletions op-challenger/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func NewConfig(
L2: l2EthRpc,
SnapshotFreq: DefaultCannonSnapshotFreq,
InfoFreq: DefaultCannonInfoFreq,
DebugInfo: true,
},
Asterisc: vm.Config{
VmType: types.TraceTypeAsterisc,
Expand Down
10 changes: 10 additions & 0 deletions op-challenger/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ func TestCannonRequiredArgs(t *testing.T) {
cfg.Cannon.Network = "unknown"
require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown)
})

t.Run(fmt.Sprintf("TestDebugInfoEnabled-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
require.True(t, cfg.Cannon.DebugInfo)
})
}
}

Expand Down Expand Up @@ -319,6 +324,11 @@ func TestAsteriscRequiredArgs(t *testing.T) {
cfg.Asterisc.Network = "unknown"
require.ErrorIs(t, cfg.Check(), ErrAsteriscNetworkUnknown)
})

t.Run(fmt.Sprintf("TestDebugInfoDisabled-%v", traceType), func(t *testing.T) {
cfg := validConfig(traceType)
require.False(t, cfg.Asterisc.DebugInfo)
})
}
}

Expand Down
1 change: 1 addition & 0 deletions op-challenger/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro
L2GenesisPath: ctx.String(CannonL2GenesisFlag.Name),
SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name),
InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name),
DebugInfo: true,
},
CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name),
CannonAbsolutePreStateBaseURL: cannonPrestatesURL,
Expand Down
22 changes: 22 additions & 0 deletions op-challenger/game/fault/trace/vm/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ import (

"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
)

const (
debugFilename = "debug-info.json"
)

type Metricer interface {
RecordVmExecutionTime(vmType string, t time.Duration)
RecordVmMemoryUsed(vmType string, memoryUsed uint64)
}

type Config struct {
Expand All @@ -31,6 +38,7 @@ type Config struct {
L2GenesisPath string
SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions)
InfoFreq uint // Frequency of progress log messages (in VM instructions)
DebugInfo bool
}

type Executor struct {
Expand Down Expand Up @@ -86,6 +94,9 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64
if end < math.MaxUint64 {
args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10))
}
if e.cfg.DebugInfo {
args = append(args, "--debug-info", filepath.Join(dataDir, debugFilename))
}
args = append(args, extraVmArgs...)
args = append(args,
"--",
Expand Down Expand Up @@ -123,5 +134,16 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64
execStart := time.Now()
err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cfg.VmBin, args...)
e.metrics.RecordVmExecutionTime(e.cfg.VmType.String(), time.Since(execStart))
if e.cfg.DebugInfo && err == nil {
if info, err := jsonutil.LoadJSON[debugInfo](filepath.Join(dataDir, debugFilename)); err != nil {
e.logger.Warn("Failed to load debug metrics", "err", err)
} else {
e.metrics.RecordVmMemoryUsed(e.cfg.VmType.String(), uint64(info.MemoryUsed))
}
}
return err
}

type debugInfo struct {
MemoryUsed hexutil.Uint64 `json:"memory_used"`
}
13 changes: 13 additions & 0 deletions op-challenger/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type Metricer interface {
RecordGameMove()
RecordGameL2Challenge()
RecordVmExecutionTime(vmType string, t time.Duration)
RecordVmMemoryUsed(vmType string, memoryUsed uint64)
RecordClaimResolutionTime(t float64)
RecordGameActTime(t float64)

Expand Down Expand Up @@ -94,6 +95,7 @@ type Metrics struct {
claimResolutionTime prometheus.Histogram
gameActTime prometheus.Histogram
vmExecutionTime *prometheus.HistogramVec
vmMemoryUsed *prometheus.HistogramVec

trackedGames prometheus.GaugeVec
inflightGames prometheus.Gauge
Expand Down Expand Up @@ -176,6 +178,13 @@ func NewMetrics() *Metrics {
[]float64{1.0, 10.0},
prometheus.ExponentialBuckets(30.0, 2.0, 14)...),
}, []string{"vm"}),
vmMemoryUsed: factory.NewHistogramVec(prometheus.HistogramOpts{
Namespace: Namespace,
Name: "vm_memory_used",
Help: "Memory used (in bytes) to execute the fault proof VM",
// 100MiB increments from 0 to 1.5GiB
Buckets: prometheus.LinearBuckets(0, 1024*1024*100, 15),
}, []string{"vm"}),
bondClaimFailures: factory.NewCounter(prometheus.CounterOpts{
Namespace: Namespace,
Name: "claim_failures",
Expand Down Expand Up @@ -285,6 +294,10 @@ func (m *Metrics) RecordVmExecutionTime(vmType string, dur time.Duration) {
m.vmExecutionTime.WithLabelValues(vmType).Observe(dur.Seconds())
}

func (m *Metrics) RecordVmMemoryUsed(vmType string, memoryUsed uint64) {
m.vmMemoryUsed.WithLabelValues(vmType).Observe(float64(memoryUsed))
}

func (m *Metrics) RecordClaimResolutionTime(t float64) {
m.claimResolutionTime.Observe(t)
}
Expand Down
1 change: 1 addition & 0 deletions op-challenger/metrics/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (*NoopMetricsImpl) RecordBondClaimFailed() {}
func (*NoopMetricsImpl) RecordBondClaimed(uint64) {}

func (*NoopMetricsImpl) RecordVmExecutionTime(_ string, _ time.Duration) {}
func (*NoopMetricsImpl) RecordVmMemoryUsed(_ string, _ uint64) {}
func (*NoopMetricsImpl) RecordClaimResolutionTime(t float64) {}
func (*NoopMetricsImpl) RecordGameActTime(t float64) {}

Expand Down
37 changes: 32 additions & 5 deletions op-challenger/runner/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ type Metrics struct {
factory opmetrics.Factory
*contractMetrics.ContractMetrics

vmExecutionTime *prometheus.HistogramVec
successTotal *prometheus.CounterVec
failuresTotal *prometheus.CounterVec
invalidTotal *prometheus.CounterVec
vmExecutionTime *prometheus.HistogramVec
vmLastExecutionTime *prometheus.GaugeVec
vmMemoryUsed *prometheus.HistogramVec
vmLastMemoryUsed *prometheus.GaugeVec
successTotal *prometheus.CounterVec
failuresTotal *prometheus.CounterVec
invalidTotal *prometheus.CounterVec
}

var _ Metricer = (*Metrics)(nil)
Expand All @@ -47,6 +50,23 @@ func NewMetrics() *Metrics {
[]float64{1.0, 10.0},
prometheus.ExponentialBuckets(30.0, 2.0, 14)...),
}, []string{"vm"}),
vmLastExecutionTime: factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "vm_last_execution_time",
Help: "Time (in seconds) taken for the last execution of the fault proof VM",
}, []string{"vm"}),
vmMemoryUsed: factory.NewHistogramVec(prometheus.HistogramOpts{
Namespace: Namespace,
Name: "vm_memory_used",
Help: "Memory used (in bytes) to execute the fault proof VM",
// 100MiB increments from 0 to 1.5GiB
Buckets: prometheus.LinearBuckets(0, 1024*1024*100, 15),
}, []string{"vm"}),
vmLastMemoryUsed: factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "vm_last_memory_used",
Help: "Memory used (in bytes) for the last execution of the fault proof VM",
}, []string{"vm"}),
successTotal: factory.NewCounterVec(prometheus.CounterOpts{
Namespace: Namespace,
Name: "success_total",
Expand All @@ -70,7 +90,14 @@ func (m *Metrics) Registry() *prometheus.Registry {
}

func (m *Metrics) RecordVmExecutionTime(vmType string, dur time.Duration) {
m.vmExecutionTime.WithLabelValues(vmType).Observe(dur.Seconds())
val := dur.Seconds()
m.vmExecutionTime.WithLabelValues(vmType).Observe(val)
m.vmLastExecutionTime.WithLabelValues(vmType).Set(val)
}

func (m *Metrics) RecordVmMemoryUsed(vmType string, memoryUsed uint64) {
m.vmMemoryUsed.WithLabelValues(vmType).Observe(float64(memoryUsed))
m.vmLastMemoryUsed.WithLabelValues(vmType).Set(float64(memoryUsed))
}

func (m *Metrics) RecordSuccess(vmType types.TraceType) {
Expand Down

0 comments on commit f940301

Please sign in to comment.