cache: Reduce memory usage

This commit is contained in:
Martin Polden 2020-09-11 20:51:04 +02:00
parent bd8b1c7b97
commit df49848167
2 changed files with 33 additions and 11 deletions

View File

@ -10,19 +10,18 @@ import (
type Cache struct { type Cache struct {
capacity int capacity int
mu sync.RWMutex mu sync.RWMutex
entries map[uint64]Response entries map[uint64]*list.Element
keys *list.List values *list.List
} }
func NewCache(capacity int) *Cache { func NewCache(capacity int) *Cache {
if capacity < 0 { if capacity < 0 {
capacity = 0 capacity = 0
} }
keys := list.New()
return &Cache{ return &Cache{
capacity: capacity, capacity: capacity,
entries: make(map[uint64]Response), entries: make(map[uint64]*list.Element),
keys: keys, values: list.New(),
} }
} }
@ -41,12 +40,17 @@ func (c *Cache) Set(ip net.IP, resp Response) {
defer c.mu.Unlock() defer c.mu.Unlock()
if len(c.entries) == c.capacity { if len(c.entries) == c.capacity {
// At capacity. Remove the oldest entry // At capacity. Remove the oldest entry
oldest := c.keys.Front() oldest := c.values.Front()
delete(c.entries, oldest.Value.(uint64)) oldestValue := oldest.Value.(Response)
c.keys.Remove(oldest) oldestKey := key(oldestValue.IP)
delete(c.entries, oldestKey)
c.values.Remove(oldest)
} }
c.entries[k] = resp current, ok := c.entries[k]
c.keys.PushBack(k) if ok {
c.values.Remove(current)
}
c.entries[k] = c.values.PushBack(resp)
} }
func (c *Cache) Get(ip net.IP) (Response, bool) { func (c *Cache) Get(ip net.IP) (Response, bool) {
@ -54,5 +58,8 @@ func (c *Cache) Get(ip net.IP) (Response, bool) {
c.mu.RLock() c.mu.RLock()
defer c.mu.RUnlock() defer c.mu.RUnlock()
r, ok := c.entries[k] r, ok := c.entries[k]
return r, ok if !ok {
return Response{}, false
}
return r.Value.(Response), true
} }

View File

@ -39,3 +39,18 @@ func TestCacheCapacity(t *testing.T) {
} }
} }
} }
func TestCacheDuplicate(t *testing.T) {
c := NewCache(10)
ip := net.ParseIP("192.0.2.1")
response := Response{IP: ip}
c.Set(ip, response)
c.Set(ip, response)
want := 1
if got := len(c.entries); got != want {
t.Errorf("want %d entries, got %d", want, got)
}
if got := c.values.Len(); got != want {
t.Errorf("want %d values, got %d", want, got)
}
}