forked from cerc-io/plugeth
cmd/evm: Add --bench flag for benchmarking (#20330)
The --bench flag uses the testing.B to execute the EVM bytecode many times and get the average exeuction time out of it.
This commit is contained in:
parent
c4b7fdd27e
commit
49cf000df7
@ -87,6 +87,10 @@ var (
|
|||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
Usage: "sets the verbosity level",
|
Usage: "sets the verbosity level",
|
||||||
}
|
}
|
||||||
|
BenchFlag = cli.BoolFlag{
|
||||||
|
Name: "bench",
|
||||||
|
Usage: "benchmark the execution",
|
||||||
|
}
|
||||||
CreateFlag = cli.BoolFlag{
|
CreateFlag = cli.BoolFlag{
|
||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "indicates the action should be create rather than call",
|
Usage: "indicates the action should be create rather than call",
|
||||||
@ -124,6 +128,7 @@ var (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
|
BenchFlag,
|
||||||
CreateFlag,
|
CreateFlag,
|
||||||
DebugFlag,
|
DebugFlag,
|
||||||
VerbosityFlag,
|
VerbosityFlag,
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
|
||||||
@ -69,6 +70,33 @@ func readGenesis(genesisPath string) *core.Genesis {
|
|||||||
return genesis
|
return genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, uint64, time.Duration, error) {
|
||||||
|
var (
|
||||||
|
output []byte
|
||||||
|
gasLeft uint64
|
||||||
|
execTime time.Duration
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if bench {
|
||||||
|
result := testing.Benchmark(func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
output, gasLeft, err = execFunc()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get the average execution time from the benchmarking result.
|
||||||
|
// There are other useful stats here that could be reported.
|
||||||
|
execTime = time.Duration(result.NsPerOp())
|
||||||
|
} else {
|
||||||
|
startTime := time.Now()
|
||||||
|
output, gasLeft, err = execFunc()
|
||||||
|
execTime = time.Since(startTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output, gasLeft, execTime, err
|
||||||
|
}
|
||||||
|
|
||||||
func runCmd(ctx *cli.Context) error {
|
func runCmd(ctx *cli.Context) error {
|
||||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||||
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
||||||
@ -116,11 +144,7 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name))
|
receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var code []byte
|
||||||
code []byte
|
|
||||||
ret []byte
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
codeFileFlag := ctx.GlobalString(CodeFileFlag.Name)
|
codeFileFlag := ctx.GlobalString(CodeFileFlag.Name)
|
||||||
codeFlag := ctx.GlobalString(CodeFlag.Name)
|
codeFlag := ctx.GlobalString(CodeFlag.Name)
|
||||||
|
|
||||||
@ -203,10 +227,10 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
} else {
|
} else {
|
||||||
runtimeConfig.ChainConfig = params.AllEthashProtocolChanges
|
runtimeConfig.ChainConfig = params.AllEthashProtocolChanges
|
||||||
}
|
}
|
||||||
tstart := time.Now()
|
|
||||||
var leftOverGas uint64
|
|
||||||
var hexInput []byte
|
var hexInput []byte
|
||||||
if inputFileFlag := ctx.GlobalString(InputFileFlag.Name); inputFileFlag != "" {
|
if inputFileFlag := ctx.GlobalString(InputFileFlag.Name); inputFileFlag != "" {
|
||||||
|
var err error
|
||||||
if hexInput, err = ioutil.ReadFile(inputFileFlag); err != nil {
|
if hexInput, err = ioutil.ReadFile(inputFileFlag); err != nil {
|
||||||
fmt.Printf("could not load input from file: %v\n", err)
|
fmt.Printf("could not load input from file: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -215,16 +239,24 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
hexInput = []byte(ctx.GlobalString(InputFlag.Name))
|
hexInput = []byte(ctx.GlobalString(InputFlag.Name))
|
||||||
}
|
}
|
||||||
input := common.FromHex(string(bytes.TrimSpace(hexInput)))
|
input := common.FromHex(string(bytes.TrimSpace(hexInput)))
|
||||||
|
|
||||||
|
var execFunc func() ([]byte, uint64, error)
|
||||||
if ctx.GlobalBool(CreateFlag.Name) {
|
if ctx.GlobalBool(CreateFlag.Name) {
|
||||||
input = append(code, input...)
|
input = append(code, input...)
|
||||||
ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig)
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
|
output, _, gasLeft, err := runtime.Create(input, &runtimeConfig)
|
||||||
|
return output, gasLeft, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
statedb.SetCode(receiver, code)
|
statedb.SetCode(receiver, code)
|
||||||
}
|
}
|
||||||
ret, leftOverGas, err = runtime.Call(receiver, input, &runtimeConfig)
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
|
return runtime.Call(receiver, input, &runtimeConfig)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
execTime := time.Since(tstart)
|
|
||||||
|
output, leftOverGas, execTime, err := timedExec(ctx.GlobalBool(BenchFlag.Name), execFunc)
|
||||||
|
|
||||||
if ctx.GlobalBool(DumpFlag.Name) {
|
if ctx.GlobalBool(DumpFlag.Name) {
|
||||||
statedb.Commit(true)
|
statedb.Commit(true)
|
||||||
@ -267,7 +299,7 @@ Gas used: %d
|
|||||||
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas)
|
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas)
|
||||||
}
|
}
|
||||||
if tracer == nil {
|
if tracer == nil {
|
||||||
fmt.Printf("0x%x\n", ret)
|
fmt.Printf("0x%x\n", output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(" error: %v\n", err)
|
fmt.Printf(" error: %v\n", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user