diff --git a/cl/persistence/state/historical_states_reader/attesting_indicies.go b/cl/persistence/state/historical_states_reader/attesting_indicies.go index 9da5eb8be79..93dd5e3b778 100644 --- a/cl/persistence/state/historical_states_reader/attesting_indicies.go +++ b/cl/persistence/state/historical_states_reader/attesting_indicies.go @@ -103,8 +103,12 @@ func (r *HistoricalStatesReader) ComputeCommittee(mix libcommon.Hash, indicies [ end := (lenIndicies * (index + 1)) / count var shuffledIndicies []uint64 - shuffledIndicies = make([]uint64, lenIndicies) - shuffledIndicies = shuffling.ComputeShuffledIndicies(cfg, mix, shuffledIndicies, indicies, slot) + shuffledIndicies, ok := r.shuffledIndiciesCache.Get(slot / cfg.SlotsPerEpoch) + if !ok { + shuffledIndicies = make([]uint64, lenIndicies) + shuffledIndicies = shuffling.ComputeShuffledIndicies(cfg, mix, shuffledIndicies, indicies, slot) + r.shuffledIndiciesCache.Add(slot/cfg.SlotsPerEpoch, shuffledIndicies) + } return shuffledIndicies[start:end], nil } diff --git a/cl/persistence/state/historical_states_reader/historical_states_reader.go b/cl/persistence/state/historical_states_reader/historical_states_reader.go index 919c35faae2..7f6b9821b84 100644 --- a/cl/persistence/state/historical_states_reader/historical_states_reader.go +++ b/cl/persistence/state/historical_states_reader/historical_states_reader.go @@ -23,6 +23,7 @@ import ( "fmt" "io" "sync" + "time" "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/kv" @@ -33,6 +34,7 @@ import ( "github.com/erigontech/erigon/cl/persistence/base_encoding" state_accessors "github.com/erigontech/erigon/cl/persistence/state" "github.com/erigontech/erigon/cl/phase1/core/state" + "github.com/erigontech/erigon/cl/phase1/core/state/lru" "github.com/erigontech/erigon/turbo/snapshotsync" "github.com/erigontech/erigon/turbo/snapshotsync/freezeblocks" "github.com/klauspost/compress/zstd" @@ -48,6 +50,8 @@ type HistoricalStatesReader struct { blockReader freezeblocks.BeaconSnapshotReader stateSn *snapshotsync.CaplinStateSnapshots genesisState *state.CachingBeaconState + + shuffledIndiciesCache *lru.CacheWithTTL[uint64, []uint64] } func NewHistoricalStatesReader( @@ -55,13 +59,15 @@ func NewHistoricalStatesReader( blockReader freezeblocks.BeaconSnapshotReader, validatorTable *state_accessors.StaticValidatorTable, genesisState *state.CachingBeaconState, stateSn *snapshotsync.CaplinStateSnapshots) *HistoricalStatesReader { + shuffledIndiciesCache := lru.NewWithTTL[uint64, []uint64]("shuffledIndiciesCacheReader", 64, 2*time.Minute) return &HistoricalStatesReader{ - cfg: cfg, - blockReader: blockReader, - genesisState: genesisState, - validatorTable: validatorTable, - stateSn: stateSn, + cfg: cfg, + blockReader: blockReader, + genesisState: genesisState, + validatorTable: validatorTable, + stateSn: stateSn, + shuffledIndiciesCache: shuffledIndiciesCache, } } diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index ff20788cf11..7fb0a50a316 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -591,7 +591,7 @@ func (r *RetrieveHistoricalState) Run(ctx *Context) error { if _, err := antiquary.FillStaticValidatorsTableIfNeeded(ctx, log.Root(), stateSn, vt); err != nil { return err } - fmt.Println(vt.WithdrawableEpoch(0, 1)) + r.withPPROF.withProfile() hr := historical_states_reader.NewHistoricalStatesReader(beaconConfig, snr, vt, gSpot, stateSn) start := time.Now() diff --git a/turbo/snapshotsync/caplin_state_snapshots.go b/turbo/snapshotsync/caplin_state_snapshots.go index f5c75568dcc..48bc93cc693 100644 --- a/turbo/snapshotsync/caplin_state_snapshots.go +++ b/turbo/snapshotsync/caplin_state_snapshots.go @@ -135,8 +135,9 @@ type CaplinStateSnapshots struct { dirtyLock sync.RWMutex // guards `dirty` field dirty map[string]*btree.BTreeG[*DirtySegment] // ordered map `type.Enum()` -> DirtySegments - visibleLock sync.RWMutex // guards `visible` field - visible map[string]VisibleSegments // ordered map `type.Enum()` -> VisbileSegments + visibleLock sync.RWMutex // guards `visible` field + visible sync.Map + //visible map[string]VisibleSegments // ordered map `type.Enum()` -> VisbileSegments snapshotTypes SnapshotTypes @@ -181,11 +182,11 @@ func NewCaplinStateSnapshots(cfg ethconfig.BlocksFreezing, beaconCfg *clparams.B for k := range snapshotTypes.KeyValueGetters { dirty[k] = btree.NewBTreeGOptions[*DirtySegment](DirtySegmentLess, btree.Options{Degree: 128, NoLocks: false}) } - visible := make(map[string]VisibleSegments) + + c := &CaplinStateSnapshots{snapshotTypes: snapshotTypes, dir: dirs.SnapCaplin, tmpdir: dirs.Tmp, cfg: cfg, dirty: dirty, logger: logger, beaconCfg: beaconCfg} for k := range snapshotTypes.KeyValueGetters { - visible[k] = make(VisibleSegments, 0) + c.visible.Store(k, make(VisibleSegments, 0)) } - c := &CaplinStateSnapshots{snapshotTypes: snapshotTypes, dir: dirs.SnapCaplin, tmpdir: dirs.Tmp, cfg: cfg, visible: visible, dirty: dirty, logger: logger, beaconCfg: beaconCfg} c.recalcVisibleFiles() return c } @@ -430,9 +431,13 @@ func (s *CaplinStateSnapshots) recalcVisibleFiles() { return newVisibleSegments } - for k := range s.visible { - s.visible[k] = getNewVisibleSegments(s.dirty[k]) - } + // for k := range s.visible { + // s.visible[k] = getNewVisibleSegments(s.dirty[k]) + // } + s.visible.Range(func(k, v interface{}) bool { + s.visible.Store(k, getNewVisibleSegments(s.dirty[k.(string)])) + return true + }) } func (s *CaplinStateSnapshots) idxAvailability() uint64 { @@ -440,14 +445,25 @@ func (s *CaplinStateSnapshots) idxAvailability() uint64 { defer s.visibleLock.RUnlock() min := uint64(math.MaxUint64) - for _, segs := range s.visible { + // for _, segs := range s.visible { + // if len(segs) == 0 { + // return 0 + // } + // if segs[len(segs)-1].to < min { + // min = segs[len(segs)-1].to + // } + // } + s.visible.Range(func(_, v interface{}) bool { + segs := v.([]*VisibleSegment) if len(segs) == 0 { - return 0 + min = 0 + return false } if segs[len(segs)-1].to < min { min = segs[len(segs)-1].to } - } + return true + }) if min == math.MaxUint64 { return 0 } @@ -523,9 +539,13 @@ func (s *CaplinStateSnapshots) View() *CaplinStateView { s.dirtySegmentsLock.RLock() defer s.dirtySegmentsLock.RUnlock() - for k, segments := range s.visible { - v.roTxs[k] = segments.BeginRo() - } + // for k, segments := range s.visible { + // v.roTxs[k] = segments.BeginRo() + // } + s.visible.Range(func(k, val interface{}) bool { + v.roTxs[k.(string)] = VisibleSegments(val.([]*VisibleSegment)).BeginRo() + return true + }) return v } @@ -544,10 +564,17 @@ func (v *CaplinStateView) Close() { } func (v *CaplinStateView) VisibleSegments(tbl string) []*VisibleSegment { - if v.s == nil || v.s.visible[tbl] == nil { + // if v.s == nil || v.s.visible[tbl] == nil { + // return nil + // } + // return v.s.visible[tbl] + if v.s == nil { return nil } - return v.s.visible[tbl] + if val, ok := v.s.visible.Load(tbl); ok { + return val.([]*VisibleSegment) + } + return nil } func (v *CaplinStateView) VisibleSegment(slot uint64, tbl string) (*VisibleSegment, bool) {