Skip to content

Commit ea09cc0

Browse files
authored
Merge pull request #2433 from analytically/lru_invalidset
perf(stmtcache): replace O(n) invalidation scan with O(1) map lookup
2 parents 1ce3d44 + 3e2f43d commit ea09cc0

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

internal/stmtcache/lru_cache.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ type LRUCache struct {
1212
m map[string]*list.Element
1313
l *list.List
1414
invalidStmts []*pgconn.StatementDescription
15+
invalidSet map[string]struct{}
1516
}
1617

1718
// NewLRUCache creates a new LRUCache. cap is the maximum size of the cache.
1819
func NewLRUCache(cap int) *LRUCache {
1920
return &LRUCache{
20-
cap: cap,
21-
m: make(map[string]*list.Element),
22-
l: list.New(),
21+
cap: cap,
22+
m: make(map[string]*list.Element),
23+
l: list.New(),
24+
invalidSet: make(map[string]struct{}),
2325
}
2426
}
2527

@@ -45,10 +47,8 @@ func (c *LRUCache) Put(sd *pgconn.StatementDescription) {
4547
}
4648

4749
// The statement may have been invalidated but not yet handled. Do not readd it to the cache.
48-
for _, invalidSD := range c.invalidStmts {
49-
if invalidSD.SQL == sd.SQL {
50-
return
51-
}
50+
if _, invalidated := c.invalidSet[sd.SQL]; invalidated {
51+
return
5252
}
5353

5454
if c.l.Len() == c.cap {
@@ -63,7 +63,9 @@ func (c *LRUCache) Put(sd *pgconn.StatementDescription) {
6363
func (c *LRUCache) Invalidate(sql string) {
6464
if el, ok := c.m[sql]; ok {
6565
delete(c.m, sql)
66-
c.invalidStmts = append(c.invalidStmts, el.Value.(*pgconn.StatementDescription))
66+
sd := el.Value.(*pgconn.StatementDescription)
67+
c.invalidStmts = append(c.invalidStmts, sd)
68+
c.invalidSet[sql] = struct{}{}
6769
c.l.Remove(el)
6870
}
6971
}
@@ -72,7 +74,9 @@ func (c *LRUCache) Invalidate(sql string) {
7274
func (c *LRUCache) InvalidateAll() {
7375
el := c.l.Front()
7476
for el != nil {
75-
c.invalidStmts = append(c.invalidStmts, el.Value.(*pgconn.StatementDescription))
77+
sd := el.Value.(*pgconn.StatementDescription)
78+
c.invalidStmts = append(c.invalidStmts, sd)
79+
c.invalidSet[sd.SQL] = struct{}{}
7680
el = el.Next()
7781
}
7882

@@ -90,6 +94,7 @@ func (c *LRUCache) GetInvalidated() []*pgconn.StatementDescription {
9094
// never seen by the call to GetInvalidated.
9195
func (c *LRUCache) RemoveInvalidated() {
9296
c.invalidStmts = nil
97+
c.invalidSet = make(map[string]struct{})
9398
}
9499

95100
// Len returns the number of cached prepared statement descriptions.
@@ -106,6 +111,7 @@ func (c *LRUCache) invalidateOldest() {
106111
oldest := c.l.Back()
107112
sd := oldest.Value.(*pgconn.StatementDescription)
108113
c.invalidStmts = append(c.invalidStmts, sd)
114+
c.invalidSet[sd.SQL] = struct{}{}
109115
delete(c.m, sd.SQL)
110116
c.l.Remove(oldest)
111117
}

0 commit comments

Comments
 (0)