From 832f3655e886b42eaf017c27c3a8c6f3cf523318 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Fri, 11 Sep 2020 21:55:09 +0200 Subject: [PATCH] http, cache: Track evictions --- http/cache.go | 21 +++++++++++++-------- http/cache_test.go | 21 ++++++++++++++++----- http/http.go | 6 ++++-- http/http_test.go | 2 +- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/http/cache.go b/http/cache.go index 6d61b20..5568d7a 100644 --- a/http/cache.go +++ b/http/cache.go @@ -9,15 +9,17 @@ import ( ) type Cache struct { - capacity int - mu sync.RWMutex - entries map[uint64]*list.Element - values *list.List + capacity int + mu sync.RWMutex + entries map[uint64]*list.Element + values *list.List + evictions uint64 } type CacheStats struct { - Capacity int - Size int + Capacity int + Size int + Evictions uint64 } func NewCache(capacity int) *Cache { @@ -55,6 +57,7 @@ func (c *Cache) Set(ip net.IP, resp Response) { el = next evicted++ } + c.evictions += uint64(evicted) } current, ok := c.entries[k] if ok { @@ -81,6 +84,7 @@ func (c *Cache) Resize(capacity int) error { c.mu.Lock() defer c.mu.Unlock() c.capacity = capacity + c.evictions = 0 return nil } @@ -88,7 +92,8 @@ func (c *Cache) Stats() CacheStats { c.mu.RLock() defer c.mu.RUnlock() return CacheStats{ - Size: len(c.entries), - Capacity: c.capacity, + Size: len(c.entries), + Capacity: c.capacity, + Evictions: c.evictions, } } diff --git a/http/cache_test.go b/http/cache_test.go index 0867958..e99d480 100644 --- a/http/cache_test.go +++ b/http/cache_test.go @@ -9,11 +9,13 @@ import ( func TestCacheCapacity(t *testing.T) { var tests = []struct { addCount, capacity, size int + evictions uint64 }{ - {1, 0, 0}, - {1, 2, 1}, - {2, 2, 2}, - {3, 2, 2}, + {1, 0, 0, 0}, + {1, 2, 1, 0}, + {2, 2, 2, 0}, + {3, 2, 2, 1}, + {10, 5, 5, 5}, } for i, tt := range tests { c := NewCache(tt.capacity) @@ -27,6 +29,9 @@ func TestCacheCapacity(t *testing.T) { if got := len(c.entries); got != tt.size { t.Errorf("#%d: len(entries) = %d, want %d", i, got, tt.size) } + if got := c.evictions; got != tt.evictions { + t.Errorf("#%d: evictions = %d, want %d", i, got, tt.evictions) + } if tt.capacity > 0 && tt.addCount > tt.capacity && tt.capacity == tt.size { lastAdded := responses[tt.addCount-1] if _, ok := c.Get(lastAdded.IP); !ok { @@ -57,7 +62,7 @@ func TestCacheDuplicate(t *testing.T) { func TestCacheResize(t *testing.T) { c := NewCache(10) - for i := 1; i <= 10; i++ { + for i := 1; i <= 20; i++ { ip := net.ParseIP(fmt.Sprintf("192.0.2.%d", i)) r := Response{IP: ip} c.Set(ip, r) @@ -65,9 +70,15 @@ func TestCacheResize(t *testing.T) { if got, want := len(c.entries), 10; got != want { t.Errorf("want %d entries, got %d", want, got) } + if got, want := c.evictions, uint64(10); got != want { + t.Errorf("want %d evictions, got %d", want, got) + } if err := c.Resize(5); err != nil { t.Fatal(err) } + if got, want := c.evictions, uint64(0); got != want { + t.Errorf("want %d evictions, got %d", want, got) + } r := Response{IP: net.ParseIP("192.0.2.42")} c.Set(r.IP, r) if got, want := len(c.entries), 5; got != want { diff --git a/http/http.go b/http/http.go index 29295b5..1054b3b 100644 --- a/http/http.go +++ b/http/http.go @@ -299,11 +299,13 @@ func (s *Server) cacheResizeHandler(w http.ResponseWriter, r *http.Request) *app func (s *Server) cacheHandler(w http.ResponseWriter, r *http.Request) *appError { cacheStats := s.cache.Stats() var data = struct { - Size int `json:"size"` - Capacity int `json:"capacity"` + Size int `json:"size"` + Capacity int `json:"capacity"` + Evictions uint64 `json:"evictions"` }{ cacheStats.Size, cacheStats.Capacity, + cacheStats.Evictions, } b, err := json.Marshal(data) if err != nil { diff --git a/http/http_test.go b/http/http_test.go index b7ee568..f96ba12 100644 --- a/http/http_test.go +++ b/http/http_test.go @@ -187,7 +187,7 @@ func TestCacheHandler(t *testing.T) { if err != nil { t.Fatal(err) } - want := `{"size":0,"capacity":100}` + want := `{"size":0,"capacity":100,"evictions":0}` if got != want { t.Errorf("got %q, want %q", got, want) }