core/filtermaps: fix snapshot data sharing and optimize row mapping cache

Clone blockLvPtrs in makeSnapshot to prevent shared slice mutation.
Reuse BasicLRU on mapRenderer struct instead of allocating a new
mutex-protected Cache per map, reducing GC pressure and eliminating
unnecessary synchronization overhead.
This commit is contained in:
Nyxen 2026-04-04 17:11:44 -04:00
parent d8cb8a962b
commit 8145af2451

View file

@ -45,6 +45,8 @@ var (
errChainUpdate = errors.New("rendered section of chain updated") errChainUpdate = errors.New("rendered section of chain updated")
) )
type lvPos struct{ rowIndex, layerIndex uint32 }
// mapRenderer represents a process that renders filter maps in a specified // mapRenderer represents a process that renders filter maps in a specified
// range according to the actual targetView. // range according to the actual targetView.
type mapRenderer struct { type mapRenderer struct {
@ -54,6 +56,8 @@ type mapRenderer struct {
finishedMaps map[uint32]*renderedMap finishedMaps map[uint32]*renderedMap
finished common.Range[uint32] finished common.Range[uint32]
iterator *logIterator iterator *logIterator
rowMappingCache lru.BasicLRU[common.Hash, lvPos]
} }
// renderedMap represents a single filter map that is being rendered in memory. // renderedMap represents a single filter map that is being rendered in memory.
@ -110,10 +114,11 @@ func (f *FilterMaps) renderMapsFromSnapshot(cp *renderedMap) (*mapRenderer, erro
lastBlock: cp.lastBlock, lastBlock: cp.lastBlock,
blockLvPtrs: slices.Clone(cp.blockLvPtrs), blockLvPtrs: slices.Clone(cp.blockLvPtrs),
}, },
finishedMaps: make(map[uint32]*renderedMap), finishedMaps: make(map[uint32]*renderedMap),
finished: common.NewRange(cp.mapIndex, 0), finished: common.NewRange(cp.mapIndex, 0),
renderBefore: math.MaxUint32, renderBefore: math.MaxUint32,
iterator: iter, iterator: iter,
rowMappingCache: lru.NewBasicLRU[common.Hash, lvPos](cachedRowMappings),
}, nil }, nil
} }
@ -131,10 +136,11 @@ func (f *FilterMaps) renderMapsFromMapBoundary(firstMap, renderBefore uint32, st
mapIndex: firstMap, mapIndex: firstMap,
lastBlock: iter.blockNumber, lastBlock: iter.blockNumber,
}, },
finishedMaps: make(map[uint32]*renderedMap), finishedMaps: make(map[uint32]*renderedMap),
finished: common.NewRange(firstMap, 0), finished: common.NewRange(firstMap, 0),
renderBefore: renderBefore, renderBefore: renderBefore,
iterator: iter, iterator: iter,
rowMappingCache: lru.NewBasicLRU[common.Hash, lvPos](cachedRowMappings),
}, nil }, nil
} }
@ -266,7 +272,7 @@ func (r *mapRenderer) makeSnapshot() {
mapIndex: r.currentMap.mapIndex, mapIndex: r.currentMap.mapIndex,
lastBlock: r.currentMap.lastBlock, lastBlock: r.currentMap.lastBlock,
lastBlockId: r.iterator.chainView.BlockId(r.currentMap.lastBlock), lastBlockId: r.iterator.chainView.BlockId(r.currentMap.lastBlock),
blockLvPtrs: r.currentMap.blockLvPtrs, blockLvPtrs: slices.Clone(r.currentMap.blockLvPtrs),
finished: true, finished: true,
headDelimiter: r.iterator.lvIndex, headDelimiter: r.iterator.lvIndex,
}) })
@ -319,9 +325,7 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
if r.iterator.lvIndex == 0 { if r.iterator.lvIndex == 0 {
r.currentMap.blockLvPtrs = []uint64{0} r.currentMap.blockLvPtrs = []uint64{0}
} }
type lvPos struct{ rowIndex, layerIndex uint32 } r.rowMappingCache.Purge()
rowMappingCache := lru.NewCache[common.Hash, lvPos](cachedRowMappings)
defer rowMappingCache.Purge()
for r.iterator.lvIndex < uint64(r.currentMap.mapIndex+1)<<r.f.logValuesPerMap && !r.iterator.finished { for r.iterator.lvIndex < uint64(r.currentMap.mapIndex+1)<<r.f.logValuesPerMap && !r.iterator.finished {
waitCnt++ waitCnt++
@ -337,7 +341,7 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
waitCnt = 0 waitCnt = 0
} }
if logValue := r.iterator.getValueHash(); logValue != (common.Hash{}) { if logValue := r.iterator.getValueHash(); logValue != (common.Hash{}) {
lvp, cached := rowMappingCache.Get(logValue) lvp, cached := r.rowMappingCache.Get(logValue)
if !cached { if !cached {
lvp = lvPos{rowIndex: r.f.rowIndex(r.currentMap.mapIndex, 0, logValue)} lvp = lvPos{rowIndex: r.f.rowIndex(r.currentMap.mapIndex, 0, logValue)}
} }
@ -348,7 +352,7 @@ func (r *mapRenderer) renderCurrentMap(stopCb func() bool) (bool, error) {
} }
r.currentMap.filterMap[lvp.rowIndex] = append(r.currentMap.filterMap[lvp.rowIndex], r.f.columnIndex(r.iterator.lvIndex, &logValue)) r.currentMap.filterMap[lvp.rowIndex] = append(r.currentMap.filterMap[lvp.rowIndex], r.f.columnIndex(r.iterator.lvIndex, &logValue))
if !cached { if !cached {
rowMappingCache.Add(logValue, lvp) r.rowMappingCache.Add(logValue, lvp)
} }
} }
if err := r.iterator.next(); err != nil { if err := r.iterator.next(); err != nil {