Skip to content

Commit 09bb8f4

Browse files
authored
Optimize Len method by counting expired items in expiration queue
1 parent 923d329 commit 09bb8f4

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

cache.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,14 +445,45 @@ func (c *Cache[K, V]) Len() int {
445445
c.items.mu.RLock()
446446
defer c.items.mu.RUnlock()
447447

448-
size := 0
449-
for _, elem := range c.items.values {
450-
if !elem.Value.(*Item[K, V]).isExpiredUnsafe() {
451-
size++
448+
total := c.items.expQueue.Len()
449+
if total == 0 {
450+
return 0
451+
}
452+
453+
// search the heap-based expQueue by BFS
454+
countExpired := func() int {
455+
var (
456+
q []int
457+
res int
458+
)
459+
460+
item := c.items.expQueue[0].Value.(*Item[K, V])
461+
if !item.isExpiredUnsafe() {
462+
return res
463+
}
464+
465+
q = append(q, 0)
466+
for len(q) > 0 {
467+
pop := q[0]
468+
q = q[1:]
469+
res++
470+
471+
for i := 1; i <= 2; i++ {
472+
idx := 2*pop + i
473+
if idx >= total {
474+
break
475+
}
476+
477+
item = c.items.expQueue[idx].Value.(*Item[K, V])
478+
if item.isExpiredUnsafe() {
479+
q = append(q, idx)
480+
}
481+
}
452482
}
483+
return res
453484
}
454485

455-
return size
486+
return total - countExpired()
456487
}
457488

458489
// Keys returns all unexpired keys in the cache.

cache_test.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -803,8 +803,19 @@ func Test_Cache_Touch(t *testing.T) {
803803
}
804804

805805
func Test_Cache_Len(t *testing.T) {
806-
cache := prepCache(time.Hour, "1", "2")
807-
addToCache(cache, time.Nanosecond, "3")
806+
cache := prepCache(time.Hour)
807+
assert.Equal(t, 0, cache.Len())
808+
809+
addToCache(cache, time.Hour, "1")
810+
assert.Equal(t, 1, cache.Len())
811+
812+
addToCache(cache, time.Nanosecond, "2")
813+
assert.Equal(t, 1, cache.Len())
814+
815+
addToCache(cache, time.Hour, "3")
816+
for i := 4; i < 30; i++ {
817+
addToCache(cache, time.Nanosecond, fmt.Sprint(i))
818+
}
808819
assert.Equal(t, 2, cache.Len())
809820
}
810821

0 commit comments

Comments
 (0)