github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/wasm/benchmark.go (about)

     1  package main
     2  
     3  import (
     4  	"github.com/PlatONnetwork/PlatON-Go/common"
     5  	"github.com/PlatONnetwork/PlatON-Go/core/lru"
     6  	"github.com/PlatONnetwork/PlatON-Go/life/exec"
     7  	"bytes"
     8  	"errors"
     9  	"fmt"
    10  	"github.com/syndtr/goleveldb/leveldb"
    11  	"gopkg.in/urfave/cli.v1"
    12  	"io/ioutil"
    13  	"os"
    14  	"runtime/pprof"
    15  	"time"
    16  )
    17  
    18  // The runner used in the unit test is mainly responsible for testing the Platonlib c++ library.
    19  // According to the wasm file in the dir scan directory, the wasm is accessed from the main entry.
    20  // The db is created according to --outdir. The test tool judges the test result based on the log information.
    21  
    22  var (
    23  	wasmFileFlag = cli.StringFlag{
    24  		Name:  "file",
    25  		Usage: "wasm file",
    26  	}
    27  
    28  	loopFlag = cli.IntFlag{
    29  		Name:  "loop",
    30  		Usage: "execute count",
    31  		Value: 1,
    32  	}
    33  
    34  	profFlag = cli.StringFlag{
    35  		Name:  "prof",
    36  		Usage: "write cpuprofie to file",
    37  	}
    38  )
    39  
    40  var benchmarkCommand = cli.Command{
    41  	Action:    benchmarkCmd,
    42  	Name:      "benchmark",
    43  	Usage:     "benchmark wasm vm",
    44  	ArgsUsage: "<dir>",
    45  	Flags: []cli.Flag{
    46  		wasmFileFlag,
    47  		outDirFlag,
    48  		loopFlag,
    49  		profFlag,
    50  	},
    51  	HideHelp: false,
    52  }
    53  
    54  func benchmarkCmd(ctx *cli.Context) error {
    55  	wasmFile := ctx.String(wasmFileFlag.Name)
    56  	outDir := ctx.String(outDirFlag.Name)
    57  	loop := ctx.Int(loopFlag.Name)
    58  	profFile := ctx.String(profFlag.Name)
    59  
    60  	if profFile != "" {
    61  		f, err := os.Create(profFile)
    62  		if err != nil {
    63  			return err
    64  		}
    65  
    66  		pprof.StartCPUProfile(f)
    67  		defer pprof.StopCPUProfile()
    68  	}
    69  
    70  	start := time.Now()
    71  
    72  	err := benchmark(wasmFile, outDir, loop)
    73  
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	end := time.Now()
    79  
    80  	fmt.Println("execute time:", end.Sub(start).String(), "loop:", loop)
    81  
    82  	return nil
    83  }
    84  func benchmark(wasmFile string, outDir string, loop int) error {
    85  	dbPath := outDir + testDBName
    86  	logStream := bytes.NewBuffer(make([]byte, 65535))
    87  	os.RemoveAll(dbPath)
    88  	db, err := leveldb.OpenFile(dbPath, nil)
    89  	if err != nil {
    90  		return errors.New(fmt.Sprintf("open leveldb %s failed :%v", dbPath, err))
    91  	}
    92  	code, err := ioutil.ReadFile(wasmFile)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	m, functionCode, err := exec.ParseModuleAndFunc(code, nil)
    98  
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	if err := lru.SetWasmDB(outDir); err != nil {
   104  		return err
   105  	}
   106  
   107  	addr := common.HexToAddress("0x43355c787c50b647c425f594b441d4bd751951c1")
   108  	lru.WasmCache().Add(addr, &lru.WasmModule{m, functionCode})
   109  
   110  	for i := 0; i < loop; i++ {
   111  		m, ok := lru.WasmCache().Get(addr)
   112  		if !ok {
   113  			return errors.New("get wasm cache error")
   114  		}
   115  		if err := runModule(m.Module, m.FunctionCode, db, logStream); err != nil {
   116  			return err
   117  		}
   118  		//lru.WasmCache().Purge()
   119  	}
   120  	db.Close()
   121  	return nil
   122  }