feat(lotus-sim): state size command
This commit is contained in:
parent
22267eb45d
commit
73ae1924bc
@ -87,6 +87,7 @@ var infoSimCommand = &cli.Command{
|
||||
infoCommitGasSimCommand,
|
||||
infoWindowPostBandwidthSimCommand,
|
||||
infoCapacityGrowthSimCommand,
|
||||
infoStateGrowthSimCommand,
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
node, err := open(cctx)
|
||||
|
139
cmd/lotus-sim/info_state.go
Normal file
139
cmd/lotus-sim/info_state.go
Normal file
@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/urfave/cli/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var infoStateGrowthSimCommand = &cli.Command{
|
||||
Name: "state-size",
|
||||
Description: "List daily state size over the course of the simulation starting at the end.",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
node, err := open(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer node.Close()
|
||||
|
||||
sim, err := node.LoadSim(cctx.Context, cctx.String("simulation"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE: This code is entirely read-bound.
|
||||
store := node.Chainstore.StateBlockstore()
|
||||
stateSize := func(ctx context.Context, c cid.Cid) (uint64, error) {
|
||||
seen := cid.NewSet()
|
||||
sema := make(chan struct{}, 40)
|
||||
var lock sync.Mutex
|
||||
var recSize func(cid.Cid) (uint64, error)
|
||||
recSize = func(c cid.Cid) (uint64, error) {
|
||||
// Not a part of the chain state.
|
||||
if err := ctx.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
visit := seen.Visit(c)
|
||||
lock.Unlock()
|
||||
// Already seen?
|
||||
if !visit {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var links []cid.Cid
|
||||
var totalSize uint64
|
||||
if err := store.View(c, func(data []byte) error {
|
||||
totalSize += uint64(len(data))
|
||||
cbg.ScanForLinks(bytes.NewReader(data), func(c cid.Cid) {
|
||||
if c.Prefix().Codec != cid.DagCBOR {
|
||||
return
|
||||
}
|
||||
|
||||
links = append(links, c)
|
||||
})
|
||||
return nil
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errCh := make(chan error, 1)
|
||||
cb := func(c cid.Cid) {
|
||||
size, err := recSize(c)
|
||||
if err != nil {
|
||||
select {
|
||||
case errCh <- err:
|
||||
default:
|
||||
}
|
||||
return
|
||||
}
|
||||
atomic.AddUint64(&totalSize, size)
|
||||
}
|
||||
asyncCb := func(c cid.Cid) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() { <-sema }()
|
||||
cb(c)
|
||||
}()
|
||||
}
|
||||
for _, link := range links {
|
||||
select {
|
||||
case sema <- struct{}{}:
|
||||
asyncCb(link)
|
||||
default:
|
||||
cb(link)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
return 0, err
|
||||
default:
|
||||
}
|
||||
|
||||
return totalSize, nil
|
||||
}
|
||||
return recSize(c)
|
||||
}
|
||||
|
||||
firstEpoch := sim.GetStart().Height()
|
||||
ts := sim.GetHead()
|
||||
lastHeight := abi.ChainEpoch(math.MaxInt64)
|
||||
for ts.Height() > firstEpoch && cctx.Err() == nil {
|
||||
if ts.Height()+builtin.EpochsInDay <= lastHeight {
|
||||
lastHeight = ts.Height()
|
||||
|
||||
parentStateSize, err := stateSize(cctx.Context, ts.ParentState())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(cctx.App.Writer, "%d: %s\n", ts.Height(), types.SizeStr(types.NewInt(parentStateSize)))
|
||||
}
|
||||
|
||||
ts, err = sim.Chainstore.LoadTipSet(ts.Parents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return cctx.Err()
|
||||
},
|
||||
}
|
Loading…
Reference in New Issue
Block a user