Add setable buffer to handle sets in order to allow a hard max size limit
Previously, items were pushed onto the frequency linked list via the promotable buffer. As a general rule, you want your protobable buffer to be quite large, since you don't want to block Gets. But because Set uses the same buffer, the cache could grow to MaxSize + cap(promotables). Sets are now "promoted" via a new "setables" buffer. These are handled exactly the same way as before, but having it be a separate buffer means they can have different capacity. Thus, using the new `SetableBuffer(int)` configuration method can help set a hard limit on the maximum size.
This commit is contained in:
11
cache.go
11
cache.go
@@ -43,6 +43,7 @@ type Cache[T any] struct {
|
||||
bucketMask uint32
|
||||
deletables chan *Item[T]
|
||||
promotables chan *Item[T]
|
||||
setables chan *Item[T]
|
||||
}
|
||||
|
||||
// Create a new cache with the specified configuration
|
||||
@@ -56,6 +57,7 @@ func New[T any](config *Configuration[T]) *Cache[T] {
|
||||
buckets: make([]*bucket[T], config.buckets),
|
||||
deletables: make(chan *Item[T], config.deleteBuffer),
|
||||
promotables: make(chan *Item[T], config.promoteBuffer),
|
||||
setables: make(chan *Item[T], config.setableBuffer),
|
||||
}
|
||||
for i := 0; i < config.buckets; i++ {
|
||||
c.buckets[i] = &bucket[T]{
|
||||
@@ -196,7 +198,7 @@ func (c *Cache[T]) set(key string, value T, duration time.Duration, track bool)
|
||||
if existing != nil {
|
||||
c.deletables <- existing
|
||||
}
|
||||
c.promotables <- item
|
||||
c.setables <- item
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -220,6 +222,8 @@ func (c *Cache[T]) worker() {
|
||||
select {
|
||||
case item := <-c.promotables:
|
||||
promoteItem(item)
|
||||
case item := <-c.setables:
|
||||
promoteItem(item)
|
||||
case item := <-c.deletables:
|
||||
c.doDelete(item)
|
||||
case control := <-cc:
|
||||
@@ -248,7 +252,7 @@ func (c *Cache[T]) worker() {
|
||||
dropped += c.gc()
|
||||
msg.done <- struct{}{}
|
||||
case controlSyncUpdates:
|
||||
doAllPendingPromotesAndDeletes(c.promotables, promoteItem, c.deletables, c.doDelete)
|
||||
doAllPendingPromotesAndDeletes(c.promotables, c.setables, promoteItem, c.deletables, c.doDelete)
|
||||
msg.done <- struct{}{}
|
||||
}
|
||||
}
|
||||
@@ -272,6 +276,7 @@ drain:
|
||||
// that were already sent by the same goroutine.
|
||||
func doAllPendingPromotesAndDeletes[T any](
|
||||
promotables <-chan *Item[T],
|
||||
setables <-chan *Item[T],
|
||||
promoteFn func(*Item[T]),
|
||||
deletables <-chan *Item[T],
|
||||
deleteFn func(*Item[T]),
|
||||
@@ -281,6 +286,8 @@ doAllPromotes:
|
||||
select {
|
||||
case item := <-promotables:
|
||||
promoteFn(item)
|
||||
case item := <-setables:
|
||||
promoteFn(item)
|
||||
default:
|
||||
break doAllPromotes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user