Skip to content

Commit

Permalink
Merge pull request #1502 from filecoin-project/feat/import-bench
Browse files Browse the repository at this point in the history
add a command to lotus-bench to benchmark importing and validating
  • Loading branch information
magik6k committed Apr 2, 2020
2 parents d060dda + beaa3df commit 11777c5
Show file tree
Hide file tree
Showing 8 changed files with 504 additions and 339 deletions.
1 change: 1 addition & 0 deletions api/api_full.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ type InvocResult struct {
MsgRct *types.MessageReceipt
InternalExecutions []*vm.ExecutionResult
Error string
Duration time.Duration
}

type MethodCall struct {
Expand Down
1 change: 1 addition & 0 deletions chain/stmgr/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func (sm *StateManager) CallRaw(ctx context.Context, msg *types.Message, bstate
MsgRct: &ret.MessageReceipt,
InternalExecutions: ret.InternalExecutions,
Error: errs,
Duration: ret.Duration,
}, nil

}
Expand Down
1 change: 1 addition & 0 deletions chain/stmgr/stmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func (sm *StateManager) ExecutionTrace(ctx context.Context, ts *types.TipSet) (c
Msg: msg,
MsgRct: &ret.MessageReceipt,
InternalExecutions: ret.InternalExecutions,
Duration: ret.Duration,
}
if ret.ActorErr != nil {
ir.Error = ret.ActorErr.Error()
Expand Down
21 changes: 16 additions & 5 deletions chain/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"reflect"
"time"

"github.com/filecoin-project/specs-actors/actors/builtin"

Expand Down Expand Up @@ -186,6 +187,7 @@ type ApplyRet struct {
ActorErr aerrors.ActorError
Penalty types.BigInt
InternalExecutions []*ExecutionResult
Duration time.Duration
}

func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
Expand Down Expand Up @@ -261,6 +263,7 @@ func checkMessage(msg *types.Message) error {
}

func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error) {
start := time.Now()
ret, actorErr, _ := vm.send(ctx, msg, nil, 0)
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
Expand All @@ -271,10 +274,12 @@ func (vm *VM) ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*Ap
ActorErr: actorErr,
InternalExecutions: nil,
Penalty: types.NewInt(0),
Duration: time.Since(start),
}, actorErr
}

func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) {
start := time.Now()
ctx, span := trace.StartSpan(ctx, "vm.ApplyMessage")
defer span.End()
msg := cmsg.VMMessage()
Expand All @@ -299,7 +304,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrOutOfGas,
GasUsed: 0,
},
Penalty: types.BigMul(msg.GasPrice, types.NewInt(uint64(msgGasCost))),
Penalty: types.BigMul(msg.GasPrice, types.NewInt(uint64(msgGasCost))),
Duration: time.Since(start),
}, nil
}

Expand All @@ -314,7 +320,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
Penalty: minerPenaltyAmount,
Duration: time.Since(start),
}, nil
}
return nil, xerrors.Errorf("failed to look up from actor: %w", err)
Expand All @@ -326,7 +333,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderInvalid,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
Penalty: minerPenaltyAmount,
Duration: time.Since(start),
}, nil
}

Expand All @@ -336,7 +344,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderStateInvalid,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
Penalty: minerPenaltyAmount,
Duration: time.Since(start),
}, nil
}

Expand All @@ -348,7 +357,8 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ExitCode: exitcode.SysErrSenderStateInvalid,
GasUsed: 0,
},
Penalty: minerPenaltyAmount,
Penalty: minerPenaltyAmount,
Duration: time.Since(start),
}, nil
}

Expand Down Expand Up @@ -423,6 +433,7 @@ func (vm *VM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet,
ActorErr: actorErr,
InternalExecutions: rt.internalExecutions,
Penalty: types.NewInt(0),
Duration: time.Since(start),
}, nil
}

Expand Down
140 changes: 140 additions & 0 deletions cmd/lotus-bench/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package main

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"runtime/pprof"
"time"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/abi"
"golang.org/x/xerrors"

"github.com/ipfs/go-datastore"
badger "github.com/ipfs/go-ds-badger2"
blockstore "github.com/ipfs/go-ipfs-blockstore"
"gopkg.in/urfave/cli.v2"
)

type TipSetExec struct {
TipSet types.TipSetKey
Trace []*api.InvocResult
Duration time.Duration
}

var importBenchCmd = &cli.Command{
Name: "import",
Usage: "benchmark chain import and validation",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "height",
Usage: "halt validation after given height",
},
},
Action: func(cctx *cli.Context) error {
if !cctx.Args().Present() {
fmt.Println("must pass car file of chain to benchmark importing")
return nil
}

cfi, err := os.Open(cctx.Args().First())
if err != nil {
return err
}
defer cfi.Close()

tdir, err := ioutil.TempDir("", "lotus-import-bench")
if err != nil {
return err
}

bds, err := badger.NewDatastore(tdir, nil)
if err != nil {
return err
}
bs := blockstore.NewBlockstore(bds)
ds := datastore.NewMapDatastore()
cs := store.NewChainStore(bs, ds, vm.Syscalls(ffiwrapper.ProofVerifier))
stm := stmgr.NewStateManager(cs)

prof, err := os.Create("import-bench.prof")
if err != nil {
return err
}
defer prof.Close()

if err := pprof.StartCPUProfile(prof); err != nil {
return err
}

head, err := cs.Import(cfi)
if err != nil {
return err
}

if h := cctx.Int64("height"); h != 0 {
tsh, err := cs.GetTipsetByHeight(context.TODO(), abi.ChainEpoch(h), head)
if err != nil {
return err
}
head = tsh
}

ts := head
tschain := []*types.TipSet{ts}
for ts.Height() != 0 {
next, err := cs.LoadTipSet(ts.Parents())
if err != nil {
return err
}

tschain = append(tschain, next)
ts = next
}

out := make([]TipSetExec, 0, len(tschain))

lastState := tschain[len(tschain)-1].ParentState()
for i := len(tschain) - 2; i >= 0; i-- {
cur := tschain[i]
log.Infof("computing state (height: %d, ts=%s)", cur.Height(), cur.Cids())
if cur.ParentState() != lastState {
return xerrors.Errorf("tipset chain had state mismatch at height %d", cur.Height())
}
start := time.Now()
st, trace, err := stm.ExecutionTrace(context.TODO(), cur)
if err != nil {
return err
}
out = append(out, TipSetExec{
TipSet: cur.Key(),
Trace: trace,
Duration: time.Since(start),
})
lastState = st
}

pprof.StopCPUProfile()

ibj, err := os.Create("import-bench.json")
if err != nil {
return err
}
defer ibj.Close()

if err := json.NewEncoder(ibj).Encode(out); err != nil {
return err
}

return nil

},
}

0 comments on commit 11777c5

Please sign in to comment.