From cdc21b8c10b8ea198cd46858b291aeba85c1a1db Mon Sep 17 00:00:00 2001 From: Magnus Kokk Date: Tue, 17 Sep 2024 14:48:22 +0300 Subject: [PATCH] Remove the Keys() method --- cache.go | 5 -- internal/backend/backend.go | 32 ++++--------- internal/backend/backend_test.go | 20 +++----- internal/backend/benchmark_test.go | 77 ------------------------------ 4 files changed, 16 insertions(+), 118 deletions(-) diff --git a/cache.go b/cache.go index f762562..2116213 100644 --- a/cache.go +++ b/cache.go @@ -51,11 +51,6 @@ func (c *Cache[K, V]) Load(key K) (value V, loaded bool) { return c.backend.Load(key) } -// Keys returns keys for initialized cache elements in the sort order specified by policy. -func (c *Cache[K, V]) Keys() []K { - return c.backend.Keys() -} - // Range iterates over initialized cache elements in no particular order or consistency. // If f returns false, range stops the iteration. // diff --git a/internal/backend/backend.go b/internal/backend/backend.go index 84485f1..9f65c68 100644 --- a/internal/backend/backend.go +++ b/internal/backend/backend.go @@ -87,34 +87,22 @@ func (b *Backend[K, V]) Load(key K) (value V, ok bool) { return zero, false } -// Keys returns keys for initialized cache elements in the sort order specified by policy. -func (b *Backend[K, V]) Keys() []K { - b.mu.Lock() - defer b.mu.Unlock() - - keys := make([]K, 0, b.list.Len()) - b.list.Do(func(elem *ringlist.Element[Record[K, V]]) bool { - keys = append(keys, elem.Value.Key) - return true - }) - - return keys -} - // Range iterates over initialized cache elements in no particular order or consistency. // If f returns false, range stops the iteration. // // f may modify the cache. func (b *Backend[K, V]) Range(f func(key K, value V) bool) { - keys := b.Keys() - - for _, key := range keys { - b.mu.Lock() - elem, ok := b.xmap[key] - initialized := ok && elem.Value.state == stateInitialized - b.mu.Unlock() + b.mu.Lock() + elems := make([]*ringlist.Element[Record[K, V]], 0, len(b.xmap)) + for _, elem := range b.xmap { + if elem.Value.state == stateInitialized { + elems = append(elems, elem) + } + } + b.mu.Unlock() - if initialized && !f(key, elem.Value.Value) { + for _, elem := range elems { + if !f(elem.Value.Key, elem.Value.Value) { return } } diff --git a/internal/backend/backend_test.go b/internal/backend/backend_test.go index 348599f..316b579 100644 --- a/internal/backend/backend_test.go +++ b/internal/backend/backend_test.go @@ -71,16 +71,6 @@ func TestFetchCallbackBlocks(t *testing.T) { Equal(t, b.Has("key1"), true) }) - t.Run("non-blocking Keys", func(t *testing.T) { - b.Fetch("key1", func() (string, error) { - return "value1", nil - }) - - keys := b.Keys() - Equal(t, len(keys), 1) - Equal(t, keys[0], "key1") - }) - t.Run("non-blocking Range", func(t *testing.T) { b.Fetch("key1", func() (string, error) { return "value1", nil @@ -433,9 +423,10 @@ func overflowAndCollectKeys(t *testing.T, b *backend.Backend[int, int], capacity // Collect all cache keys, then overflow the cache and observe which key disappears. t.Log("collecting current cache state") oldKeys := map[int]struct{}{} - for _, key := range b.Keys() { + b.Range(func(key int, value int) bool { oldKeys[key] = struct{}{} - } + return true + }) Equal(t, len(oldKeys), capacity) t.Logf("store: %v", i) @@ -446,9 +437,10 @@ func overflowAndCollectKeys(t *testing.T, b *backend.Backend[int, int], capacity t.Log("collecting new cache state") newKeys := map[int]struct{}{} - for _, key := range b.Keys() { + b.Range(func(key int, value int) bool { newKeys[key] = struct{}{} - } + return true + }) Equal(t, len(oldKeys), capacity) t.Log("determining the evicted key") diff --git a/internal/backend/benchmark_test.go b/internal/backend/benchmark_test.go index 9b18977..87d3fd4 100644 --- a/internal/backend/benchmark_test.go +++ b/internal/backend/benchmark_test.go @@ -131,83 +131,6 @@ func BenchmarkSliceSort(b *testing.B) { }) } -func BenchmarkBackendGC(b *testing.B) { - for _, n := range []int{ - 1e3, - 1e4, - 1e5, - 1e6, - } { - b.Run(fmt.Sprint(n), newTimePerElementBench( - func() (*backend.Backend[int, int], int) { - var be backend.Backend[int, int] - be.Init(n, "", 0, 0) - for i := 0; i < n; i++ { - be.Store(i, 0) - } - - return &be, be.Len() - }, - func(be *backend.Backend[int, int]) { - keys := be.Keys() - runtime.KeepAlive(keys) - }, - )) - } -} - -func BenchmarkBackendGCLFU(b *testing.B) { - for _, n := range []int{ - 1e3, - 1e4, - 1e5, - 1e6, - } { - b.Run(fmt.Sprint(n), newTimePerElementBench( - func() (*backend.Backend[int, int], int) { - var be backend.Backend[int, int] - be.Init(n, backend.LFU, 0, 0) - - for i := 0; i < n; i++ { - be.Store(i, 0) - } - - return &be, be.Len() - }, - func(be *backend.Backend[int, int]) { - keys := be.Keys() - runtime.KeepAlive(keys) - }, - )) - } -} - -func BenchmarkBackendGCLRU(b *testing.B) { - for _, n := range []int{ - 1e3, - 1e4, - 1e5, - 1e6, - } { - b.Run(fmt.Sprint(n), newTimePerElementBench( - func() (*backend.Backend[int, int], int) { - var be backend.Backend[int, int] - be.Init(n, backend.LRU, 0, 0) - - for i := 0; i < n; i++ { - be.Store(i, 0) - } - - return &be, be.Len() - }, - func(be *backend.Backend[int, int]) { - keys := be.Keys() - runtime.KeepAlive(keys) - }, - )) - } -} - func createSlice[K comparable, V any](n int, valueFn func(*K, *V)) []*backend.Record[K, V] { items := make([]*backend.Record[K, V], n) for i := 0; i < len(items); i++ {