|
|
|
@ -25,6 +25,7 @@ import ( |
|
|
|
|
"os" |
|
|
|
|
goruntime "runtime" |
|
|
|
|
"runtime/pprof" |
|
|
|
|
"testing" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" |
|
|
|
@ -69,6 +70,33 @@ func readGenesis(genesisPath string) *core.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 { |
|
|
|
|
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) |
|
|
|
|
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)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
code []byte |
|
|
|
|
ret []byte |
|
|
|
|
err error |
|
|
|
|
) |
|
|
|
|
var code []byte |
|
|
|
|
codeFileFlag := ctx.GlobalString(CodeFileFlag.Name) |
|
|
|
|
codeFlag := ctx.GlobalString(CodeFlag.Name) |
|
|
|
|
|
|
|
|
@ -203,10 +227,10 @@ func runCmd(ctx *cli.Context) error { |
|
|
|
|
} else { |
|
|
|
|
runtimeConfig.ChainConfig = params.AllEthashProtocolChanges |
|
|
|
|
} |
|
|
|
|
tstart := time.Now() |
|
|
|
|
var leftOverGas uint64 |
|
|
|
|
|
|
|
|
|
var hexInput []byte |
|
|
|
|
if inputFileFlag := ctx.GlobalString(InputFileFlag.Name); inputFileFlag != "" { |
|
|
|
|
var err error |
|
|
|
|
if hexInput, err = ioutil.ReadFile(inputFileFlag); err != nil { |
|
|
|
|
fmt.Printf("could not load input from file: %v\n", err) |
|
|
|
|
os.Exit(1) |
|
|
|
@ -215,16 +239,24 @@ func runCmd(ctx *cli.Context) error { |
|
|
|
|
hexInput = []byte(ctx.GlobalString(InputFlag.Name)) |
|
|
|
|
} |
|
|
|
|
input := common.FromHex(string(bytes.TrimSpace(hexInput))) |
|
|
|
|
|
|
|
|
|
var execFunc func() ([]byte, uint64, error) |
|
|
|
|
if ctx.GlobalBool(CreateFlag.Name) { |
|
|
|
|
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 { |
|
|
|
|
if len(code) > 0 { |
|
|
|
|
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) { |
|
|
|
|
statedb.Commit(true) |
|
|
|
@ -267,7 +299,7 @@ Gas used: %d |
|
|
|
|
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) |
|
|
|
|
} |
|
|
|
|
if tracer == nil { |
|
|
|
|
fmt.Printf("0x%x\n", ret) |
|
|
|
|
fmt.Printf("0x%x\n", output) |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Printf(" error: %v\n", err) |
|
|
|
|
} |
|
|
|
|