incorporate ExecStats into StateTestResult. add gas used to ExecStats

This commit is contained in:
Jared Wasinger 2024-10-01 14:50:36 +07:00
parent b8ed3deee7
commit 20256a1475
2 changed files with 39 additions and 46 deletions

View file

@ -74,37 +74,41 @@ func readGenesis(genesisPath string) *core.Genesis {
return genesis return genesis
} }
type execStats struct { type ExecStats struct {
time time.Duration // The execution time. Time time.Duration `json:"time"` // The execution Time.
allocs int64 // The number of heap allocations during execution. Allocs int64 `json:"allocs"` // The number of heap allocations during execution.
bytesAllocated int64 // The cumulative number of bytes allocated during execution. BytesAllocated int64 `json:"bytesAllocated"` // The cumulative number of bytes allocated during execution.
GasUsed uint64 `json:"gasUsed"` // the amount of gas used during execution
} }
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []byte, gasLeft uint64, stats execStats, err error) { func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []byte, stats ExecStats, err error) {
var gasUsed uint64
if bench { if bench {
result := testing.Benchmark(func(b *testing.B) { result := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
output, gasLeft, err = execFunc() output, gasUsed, err = execFunc()
} }
}) })
// Get the average execution time from the benchmarking result. // Get the average execution time from the benchmarking result.
// There are other useful stats here that could be reported. // There are other useful stats here that could be reported.
stats.time = time.Duration(result.NsPerOp()) stats.Time = time.Duration(result.NsPerOp())
stats.allocs = result.AllocsPerOp() stats.Allocs = result.AllocsPerOp()
stats.bytesAllocated = result.AllocedBytesPerOp() stats.BytesAllocated = result.AllocedBytesPerOp()
stats.GasUsed = gasUsed
} else { } else {
g
var memStatsBefore, memStatsAfter goruntime.MemStats var memStatsBefore, memStatsAfter goruntime.MemStats
goruntime.ReadMemStats(&memStatsBefore) goruntime.ReadMemStats(&memStatsBefore)
startTime := time.Now() startTime := time.Now()
output, gasLeft, err = execFunc() output, gasUsed, err = execFunc()
stats.time = time.Since(startTime) stats.Time = time.Since(startTime)
goruntime.ReadMemStats(&memStatsAfter) goruntime.ReadMemStats(&memStatsAfter)
stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs) stats.Allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc) stats.BytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc)
stats.GasUsed = gasUsed
} }
return output, gasLeft, stats, err return output, stats, err
} }
func runCmd(ctx *cli.Context) error { func runCmd(ctx *cli.Context) error {
@ -264,12 +268,13 @@ func runCmd(ctx *cli.Context) error {
statedb.SetCode(receiver, code) statedb.SetCode(receiver, code)
} }
execFunc = func() ([]byte, uint64, error) { execFunc = func() ([]byte, uint64, error) {
return runtime.Call(receiver, input, &runtimeConfig) output, gasLeft, err := runtime.Call(receiver, input, &runtimeConfig)
return output, initialGas - gasLeft, err
} }
} }
bench := ctx.Bool(BenchFlag.Name) bench := ctx.Bool(BenchFlag.Name)
output, leftOverGas, stats, err := timedExec(bench, execFunc) output, stats, err := timedExec(bench, execFunc)
if ctx.Bool(DumpFlag.Name) { if ctx.Bool(DumpFlag.Name) {
root, err := statedb.Commit(genesisConfig.Number, true) root, err := statedb.Commit(genesisConfig.Number, true)
@ -299,7 +304,7 @@ func runCmd(ctx *cli.Context) error {
execution time: %v execution time: %v
allocations: %d allocations: %d
allocated bytes: %d allocated bytes: %d
`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated) `, stats.GasUsed, stats.Time, stats.Allocs, stats.BytesAllocated)
} }
if tracer == nil { if tracer == nil {
fmt.Printf("%#x\n", output) fmt.Printf("%#x\n", output)

View file

@ -20,10 +20,6 @@ import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"testing"
"time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
@ -32,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/tests" "github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"os"
) )
var ( var (
@ -73,6 +70,7 @@ type StatetestResult struct {
Fork string `json:"fork"` Fork string `json:"fork"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
State *state.Dump `json:"state,omitempty"` State *state.Dump `json:"state,omitempty"`
BenchStats *ExecStats `json:"benchStats,omitempty"`
} }
func stateTestCmd(ctx *cli.Context) error { func stateTestCmd(ctx *cli.Context) error {
@ -177,6 +175,13 @@ func runStateTest(ctx *cli.Context, fname string, cfg vm.Config, dump bool, benc
result.Pass, result.Error = false, err.Error() result.Pass, result.Error = false, err.Error()
} }
}) })
if bench {
_, stats, _ := timedExec(true, func() ([]byte, uint64, error) {
_, _, gasUsed, _ := test.test.RunNoVerify(test.st, cfg, false, rawdb.HashScheme)
return nil, gasUsed, nil
})
result.BenchStats = &stats
}
results = append(results, *result) results = append(results, *result)
} }
out, _ := json.MarshalIndent(results, "", " ") out, _ := json.MarshalIndent(results, "", " ")
@ -187,23 +192,6 @@ func runStateTest(ctx *cli.Context, fname string, cfg vm.Config, dump bool, benc
} else if len(matchingTests) != 1 { } else if len(matchingTests) != 1 {
return fmt.Errorf("can only benchmark single state test case (more than one matching params)") return fmt.Errorf("can only benchmark single state test case (more than one matching params)")
} }
var gasUsed uint64
result := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
test := matchingTests[0]
_, _, gasUsed, _ = test.test.RunNoVerify(test.st, cfg, false, rawdb.HashScheme)
}
})
var stats execStats
// Get the average execution time from the benchmarking result.
// There are other useful stats here that could be reported.
stats.time = time.Duration(result.NsPerOp())
stats.allocs = result.AllocsPerOp()
stats.bytesAllocated = result.AllocedBytesPerOp()
fmt.Fprintf(os.Stderr, `EVM gas used: %d
execution time: %v
allocations: %d
allocated bytes: %d
`, gasUsed, stats.time, stats.allocs, stats.bytesAllocated)
return nil return nil
} }