Skip to content

Commit d230a37

Browse files
committed
feat: LRU cache for signers
Signed-off-by: Ji Hwan <jkim@polygon.technology>
1 parent fd733ae commit d230a37

File tree

1 file changed

+97
-31
lines changed

1 file changed

+97
-31
lines changed

cmd/monitorv2/renderer/tview_renderer.go

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package renderer
22

33
import (
4+
"container/list"
45
"context"
56
"encoding/hex"
67
"encoding/json"
@@ -29,6 +30,83 @@ var zeroAddress = common.Address{}
2930
// Maximum number of blocks to store and display
3031
const maxBlocks = 1000
3132

33+
// Maximum number of signer cache entries (LRU eviction when exceeded)
34+
const maxSignerCacheSize = 1000
35+
36+
// signerCacheEntry represents an entry in the LRU cache
37+
type signerCacheEntry struct {
38+
key string
39+
value string
40+
}
41+
42+
// signerLRUCache implements a simple LRU cache for signer addresses
43+
type signerLRUCache struct {
44+
capacity int
45+
cache map[string]*list.Element
46+
lruList *list.List
47+
mu sync.RWMutex
48+
}
49+
50+
// newSignerLRUCache creates a new LRU cache with the given capacity
51+
func newSignerLRUCache(capacity int) *signerLRUCache {
52+
return &signerLRUCache{
53+
capacity: capacity,
54+
cache: make(map[string]*list.Element),
55+
lruList: list.New(),
56+
}
57+
}
58+
59+
// get retrieves a value from the cache and marks it as recently used
60+
func (c *signerLRUCache) get(key string) (string, bool) {
61+
c.mu.RLock()
62+
elem, exists := c.cache[key]
63+
c.mu.RUnlock()
64+
65+
if !exists {
66+
return "", false
67+
}
68+
69+
c.mu.Lock()
70+
c.lruList.MoveToFront(elem)
71+
c.mu.Unlock()
72+
73+
return elem.Value.(*signerCacheEntry).value, true
74+
}
75+
76+
// put adds or updates a value in the cache
77+
func (c *signerLRUCache) put(key, value string) {
78+
c.mu.Lock()
79+
defer c.mu.Unlock()
80+
81+
// Check if key already exists
82+
if elem, exists := c.cache[key]; exists {
83+
// Update existing entry and move to front
84+
c.lruList.MoveToFront(elem)
85+
elem.Value.(*signerCacheEntry).value = value
86+
return
87+
}
88+
89+
// Add new entry
90+
entry := &signerCacheEntry{key: key, value: value}
91+
elem := c.lruList.PushFront(entry)
92+
c.cache[key] = elem
93+
94+
// Evict least recently used if over capacity
95+
if c.lruList.Len() > c.capacity {
96+
c.evictOldest()
97+
}
98+
}
99+
100+
// evictOldest removes the least recently used entry (must be called with lock held)
101+
func (c *signerLRUCache) evictOldest() {
102+
elem := c.lruList.Back()
103+
if elem != nil {
104+
c.lruList.Remove(elem)
105+
entry := elem.Value.(*signerCacheEntry)
106+
delete(c.cache, entry.key)
107+
}
108+
}
109+
32110
// Comparison functions for different data types
33111
func compareNumbers(a, b interface{}) int {
34112
aNum := a.(*big.Int)
@@ -87,10 +165,9 @@ type TviewRenderer struct {
87165
// Map to store blocks by hash for parent lookup
88166
blocksByHash map[string]rpctypes.PolyBlock
89167
// Column definitions for sorting
90-
columns []ColumnDef
91-
// Signer cache to avoid expensive Ecrecover operations
92-
signerCache map[string]string // block hash -> signer address
93-
signerCacheMu sync.RWMutex
168+
columns []ColumnDef
169+
// Signer LRU cache to avoid expensive Ecrecover operations
170+
signerCache *signerLRUCache
94171
// View state management
95172
viewState ViewState
96173
// Mutex for thread-safe access to blocks and viewState
@@ -157,12 +234,12 @@ func NewTviewRenderer(indexer *indexer.Indexer) *TviewRenderer {
157234
columns := createColumnDefinitions()
158235

159236
renderer := &TviewRenderer{
160-
BaseRenderer: NewBaseRenderer(indexer),
161-
app: app,
162-
blocks: make([]rpctypes.PolyBlock, 0),
163-
blocksByHash: make(map[string]rpctypes.PolyBlock),
164-
columns: columns,
165-
signerCache: make(map[string]string),
237+
BaseRenderer: NewBaseRenderer(indexer),
238+
app: app,
239+
blocks: make([]rpctypes.PolyBlock, 0),
240+
blocksByHash: make(map[string]rpctypes.PolyBlock),
241+
columns: columns,
242+
signerCache: newSignerLRUCache(maxSignerCacheSize),
166243
viewState: ViewState{
167244
followMode: true, // Start in follow mode
168245
sortColumn: "number", // Default sort by block number
@@ -570,45 +647,34 @@ func (t *TviewRenderer) throttledDraw() {
570647
}
571648
}
572649

573-
// getCachedSigner gets the signer for a block, using cache to avoid expensive Ecrecover calls
650+
// getCachedSigner gets the signer for a block, using LRU cache to avoid expensive Ecrecover calls
574651
func (t *TviewRenderer) getCachedSigner(block rpctypes.PolyBlock) string {
575652
blockHash := block.Hash().Hex()
576-
653+
577654
// Check cache first
578-
t.signerCacheMu.RLock()
579-
if cached, exists := t.signerCache[blockHash]; exists {
580-
t.signerCacheMu.RUnlock()
655+
if cached, exists := t.signerCache.get(blockHash); exists {
581656
return cached
582657
}
583-
t.signerCacheMu.RUnlock()
584-
658+
585659
// If miner is non-zero, use the miner
586660
zeroAddr := common.Address{}
587661
if block.Miner() != zeroAddr {
588662
result := truncateHash(block.Miner().Hex(), 6, 4)
589-
// Cache the result
590-
t.signerCacheMu.Lock()
591-
t.signerCache[blockHash] = result
592-
t.signerCacheMu.Unlock()
663+
t.signerCache.put(blockHash, result)
593664
return result
594665
}
595-
596-
// If miner is zero, try to extract signer from extra data
666+
667+
// If miner is zero, try to extract signer from extra data (EXPENSIVE - Ecrecover)
597668
if signer, err := polymetrics.Ecrecover(&block); err == nil {
598669
signerAddr := common.HexToAddress("0x" + hex.EncodeToString(signer))
599670
result := truncateHash(signerAddr.Hex(), 6, 4)
600-
// Cache the result
601-
t.signerCacheMu.Lock()
602-
t.signerCache[blockHash] = result
603-
t.signerCacheMu.Unlock()
671+
t.signerCache.put(blockHash, result)
604672
return result
605673
}
606-
674+
607675
// If can't extract signer, cache N/A result
608676
result := "N/A"
609-
t.signerCacheMu.Lock()
610-
t.signerCache[blockHash] = result
611-
t.signerCacheMu.Unlock()
677+
t.signerCache.put(blockHash, result)
612678
return result
613679
}
614680

0 commit comments

Comments
 (0)