dont waste work when calling ComputeTipSetState in parallel

This commit is contained in:
whyrusleeping 2019-12-08 18:07:44 +01:00
parent d934f03d70
commit e8c43d00cc

View File

@ -27,14 +27,16 @@ var log = logging.Logger("statemgr")
type StateManager struct {
cs *store.ChainStore
stCache map[string][]cid.Cid
stlk sync.Mutex
stCache map[string][]cid.Cid
compWait map[string]chan struct{}
stlk sync.Mutex
}
func NewStateManager(cs *store.ChainStore) *StateManager {
return &StateManager{
cs: cs,
stCache: make(map[string][]cid.Cid),
cs: cs,
stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}),
}
}
@ -46,7 +48,7 @@ func cidsToKey(cids []cid.Cid) string {
return out
}
func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (cid.Cid, cid.Cid, error) {
func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st cid.Cid, rec cid.Cid, err error) {
ctx, span := trace.StartSpan(ctx, "tipSetState")
defer span.End()
if span.IsRecordingEvents() {
@ -55,12 +57,37 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (cid.
ck := cidsToKey(ts.Cids())
sm.stlk.Lock()
cw, cwok := sm.compWait[ck]
if cwok {
sm.stlk.Unlock()
span.AddAttributes(trace.BoolAttribute("waited", true))
select {
case <-cw:
sm.stlk.Lock()
case <-ctx.Done():
return cid.Undef, cid.Undef, ctx.Err()
}
}
cached, ok := sm.stCache[ck]
sm.stlk.Unlock()
if ok {
sm.stlk.Unlock()
span.AddAttributes(trace.BoolAttribute("cache", true))
return cached[0], cached[1], nil
}
ch := make(chan struct{})
sm.compWait[ck] = ch
defer func() {
sm.stlk.Lock()
delete(sm.compWait, ck)
if st != cid.Undef {
sm.stCache[ck] = []cid.Cid{st, rec}
}
sm.stlk.Unlock()
close(ch)
}()
sm.stlk.Unlock()
if ts.Height() == 0 {
// NB: This is here because the process that executes blocks requires that the
@ -70,14 +97,11 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (cid.
return ts.Blocks()[0].ParentStateRoot, ts.Blocks()[0].ParentMessageReceipts, nil
}
st, rec, err := sm.computeTipSetState(ctx, ts.Blocks(), nil)
st, rec, err = sm.computeTipSetState(ctx, ts.Blocks(), nil)
if err != nil {
return cid.Undef, cid.Undef, err
}
sm.stlk.Lock()
sm.stCache[ck] = []cid.Cid{st, rec}
sm.stlk.Unlock()
return st, rec, nil
}