Commit ab89972d authored by 袁兴强's avatar 袁兴强 Committed by vipwzw

add wasm vm cache

parent db7506a5
......@@ -74,7 +74,6 @@ func (w *Wasm) Exec_Create(payload *types2.WasmCreate, tx *types.Transaction, in
}
func (w *Wasm) Exec_Call(payload *types2.WasmCall, tx *types.Transaction, index int) (*types.Receipt, error) {
log.Info("into wasm Exec_Call...")
if payload == nil {
return nil, types.ErrInvalidParam
}
......@@ -83,11 +82,14 @@ func (w *Wasm) Exec_Call(payload *types2.WasmCall, tx *types.Transaction, index
}
w.stateKVC = dapp.NewKVCreator(w.GetStateDB(), calcStatePrefix(payload.Contract), nil)
var vm *exec.VirtualMachine
var ok bool
if vm, ok = w.VMCache[payload.Contract]; !ok {
code, err := w.stateKVC.GetNoPrefix(contractKey(payload.Contract))
if err != nil {
return nil, err
}
vm, err := exec.NewVirtualMachine(code, exec.VMConfig{
vm, err = exec.NewVirtualMachine(code, exec.VMConfig{
DefaultMemoryPages: 128,
DefaultTableSize: 128,
DisableFloatingPoint: true,
......@@ -96,6 +98,11 @@ func (w *Wasm) Exec_Call(payload *types2.WasmCall, tx *types.Transaction, index
if err != nil {
return nil, err
}
w.VMCache[payload.Contract] = vm
} else {
vm.Config.GasLimit = uint64(tx.Fee)
vm.Gas = 0
}
// Get the function ID of the entry function to be executed.
entryID, ok := vm.GetFunctionExport(payload.Method)
......@@ -115,7 +122,6 @@ func (w *Wasm) Exec_Call(payload *types2.WasmCall, tx *types.Transaction, index
if err != nil {
return nil, err
}
var kvs []*types.KeyValue
kvs = append(kvs, w.kvs...)
kvs = append(kvs, w.stateKVC.KVList()...)
......
......@@ -6,6 +6,7 @@ import (
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
types2 "github.com/33cn/plugin/plugin/dapp/wasm/types"
"github.com/perlin-network/life/exec"
)
var driverName = types2.WasmX
......@@ -36,10 +37,13 @@ type Wasm struct {
customLogs []string
execAddr string
contractName string
VMCache map[string]*exec.VirtualMachine
}
func newWasm() drivers.Driver {
d := &Wasm{}
d := &Wasm{
VMCache: make(map[string]*exec.VirtualMachine),
}
d.SetChild(d)
d.SetExecutorType(types.LoadExecutorType(driverName))
return d
......
package executor
import (
"encoding/hex"
"io/ioutil"
"strings"
"testing"
......@@ -41,10 +42,54 @@ func init() {
Init(types2.WasmX, cfg, nil)
}
func BenchmarkWasm_Exec_Call(b *testing.B) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
acc := initAccount(ldb)
testCreate(b, acc, kvdb)
testCall(b, acc, kvdb)
payload := types2.WasmAction{
Ty: types2.WasmActionCall,
Value: &types2.WasmAction_Call{
Call: &types2.WasmCall{
Contract: "dice",
Method: "play",
Parameters: []int64{1, 10},
},
},
}
tx := &types.Transaction{
Payload: types.Encode(&payload),
}
tx, err := types.FormatTx(cfg, types2.WasmX, tx)
require.Nil(b, err, "format tx error")
err = signTx(tx, PrivKeys[1])
require.Nil(b, err)
wasm := newWasm()
wasm.SetCoinsAccount(acc)
wasm.SetStateDB(kvdb)
api := mocks.QueueProtocolAPI{}
api.On("GetConfig").Return(cfg)
api.On("GetRandNum", mock.Anything).Return(hex.DecodeString("0x0b1f047927e1c42327bdd3222558eaf7b10b998e7a9bb8144e4b2a27ffa53df3"))
wasm.SetAPI(&api)
wasmCB = wasm.(*Wasm)
err = transferToExec(Addrs[1], wasmAddr, 1e9)
require.Nil(b, err)
wasmCB = nil
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := wasm.Exec(tx, 0)
require.Nil(b, err)
}
b.StopTimer()
}
func TestWasm_Exec(t *testing.T) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
acc := initAccount(t, ldb)
acc := initAccount(ldb)
testCreate(t, acc, kvdb)
testCall(t, acc, kvdb)
......@@ -54,7 +99,7 @@ func TestWasm_Callback(t *testing.T) {
dir, ldb, kvdb := util.CreateTestDB()
defer util.CloseTestDB(dir, ldb)
wasmCB = newWasm().(*Wasm)
acc := initAccount(t, ldb)
acc := initAccount(ldb)
wasmCB.SetCoinsAccount(acc)
wasmCB.SetStateDB(kvdb)
wasmCB.SetLocalDB(kvdb)
......@@ -218,7 +263,7 @@ func TestWasm_Callback(t *testing.T) {
t.Log(random)
}
func testCreate(t *testing.T, acc *account.DB, stateDB db.KV) {
func testCreate(t testing.TB, acc *account.DB, stateDB db.KV) {
code, err := ioutil.ReadFile("../contracts/dice/dice.wasm")
require.Nil(t, err, "read wasm file error")
payload := types2.WasmAction{
......@@ -253,7 +298,7 @@ func testCreate(t *testing.T, acc *account.DB, stateDB db.KV) {
require.Nil(t, err)
}
func testCall(t *testing.T, acc *account.DB, stateDB db.KV) {
func testCall(t testing.TB, acc *account.DB, stateDB db.KV) {
payload := types2.WasmAction{
Ty: types2.WasmActionCall,
Value: &types2.WasmAction_Call{
......@@ -287,16 +332,18 @@ func testCall(t *testing.T, acc *account.DB, stateDB db.KV) {
require.Equal(t, int32(types2.TyLogWasmCall), receipt.Logs[0].Ty)
}
func initAccount(t *testing.T, db db.KV) *account.DB {
func initAccount(db db.KV) *account.DB {
wasmAddr = address.ExecAddress(cfg.ExecName(types2.WasmX))
acc, err := account.NewAccountDB(cfg, "coins", "bty", db)
require.Nil(t, err, "new account db error")
if err != nil {
panic(err)
}
acc.SaveAccount(&types.Account{
Balance: 1e10,
Balance: 1e15,
Addr: Addrs[0],
})
acc.SaveAccount(&types.Account{
Balance: 1e10,
Balance: 1e15,
Addr: Addrs[1],
})
return acc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment