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
}
type execStats struct {
time time.Duration // The execution time.
allocs int64 // The number of heap allocations during execution.
bytesAllocated int64 // The cumulative number of bytes allocated during execution.
type ExecStats struct {
Time time.Duration `json:"time"` // The execution Time.
Allocs int64 `json:"allocs"` // The number of heap allocations 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 {
result := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
output, gasLeft, err = execFunc()
output, gasUsed, err = execFunc()
}
})
// 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()
stats.Time = time.Duration(result.NsPerOp())
stats.Allocs = result.AllocsPerOp()
stats.BytesAllocated = result.AllocedBytesPerOp()
stats.GasUsed = gasUsed
} else {
g
var memStatsBefore, memStatsAfter goruntime.MemStats
goruntime.ReadMemStats(&memStatsBefore)
startTime := time.Now()
output, gasLeft, err = execFunc()
stats.time = time.Since(startTime)
output, gasUsed, err = execFunc()
stats.Time = time.Since(startTime)
goruntime.ReadMemStats(&memStatsAfter)
stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc)
stats.Allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs)
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 {
@ -264,12 +268,13 @@ func runCmd(ctx *cli.Context) error {
statedb.SetCode(receiver, code)
}
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)
output, leftOverGas, stats, err := timedExec(bench, execFunc)
output, stats, err := timedExec(bench, execFunc)
if ctx.Bool(DumpFlag.Name) {
root, err := statedb.Commit(genesisConfig.Number, true)
@ -299,7 +304,7 @@ func runCmd(ctx *cli.Context) error {
execution time: %v
allocations: %d
allocated bytes: %d
`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated)
`, stats.GasUsed, stats.Time, stats.Allocs, stats.BytesAllocated)
}
if tracer == nil {
fmt.Printf("%#x\n", output)

View file

@ -20,10 +20,6 @@ import (
"bufio"
"encoding/json"
"fmt"
"os"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
@ -32,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
"os"
)
var (
@ -67,12 +64,13 @@ var stateTestCommand = &cli.Command{
// StatetestResult contains the execution status after running a state test, any
// error that might have occurred and a dump of the final state if requested.
type StatetestResult struct {
Name string `json:"name"`
Pass bool `json:"pass"`
Root *common.Hash `json:"stateRoot,omitempty"`
Fork string `json:"fork"`
Error string `json:"error,omitempty"`
State *state.Dump `json:"state,omitempty"`
Name string `json:"name"`
Pass bool `json:"pass"`
Root *common.Hash `json:"stateRoot,omitempty"`
Fork string `json:"fork"`
Error string `json:"error,omitempty"`
State *state.Dump `json:"state,omitempty"`
BenchStats *ExecStats `json:"benchStats,omitempty"`
}
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()
}
})
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)
}
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 {
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
}