Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for a default TTL #8

Merged
merged 3 commits into from Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
116 changes: 53 additions & 63 deletions README.md
Expand Up @@ -70,12 +70,14 @@ cache.StartJanitor()
| WithMaxSize | Sets the max size of the cache. `gocache.NoMaxSize` means there is no limit. If not set, the default max size is `gocache.DefaultMaxSize`. |
| WithMaxMemoryUsage | Sets the max memory usage of the cache. `gocache.NoMaxMemoryUsage` means there is no limit. The default behavior is to not evict based on memory usage. |
| WithEvictionPolicy | Sets the eviction algorithm to be used when the cache reaches the max size. If not set, the default eviction policy is `gocache.FirstInFirstOut` (FIFO). |
| WithDefaultTTL | Sets the default TTL for each entry. |
| WithForceNilInterfaceOnNilPointer | Configures whether values with a nil pointer passed to write functions should be forcefully set to nil. Defaults to true. |
| StartJanitor | Starts the janitor, which is in charge of deleting expired cache entries in the background. |
| StopJanitor | Stops the janitor. |
| Set | Same as `SetWithTTL`, but with no expiration (`gocache.NoExpiration`) |
| SetAll | Same as `Set`, but in bulk |
| Set | Same as `SetWithTTL`, but using the default TTL (which is `gocache.NoExpiration`, unless configured otherwise). |
| SetWithTTL | Creates or updates a cache entry with the given key, value and expiration time. If the max size after the aforementioned operation is above the configured max size, the tail will be evicted. Depending on the eviction policy, the tail is defined as the oldest |
| SetAll | Same as `Set`, but in bulk. |
| SetAllWithTTL | Same as `SetWithTTL`, but in bulk. |
| Get | Gets a cache entry by its key. |
| GetByKeys | Gets a map of entries by their keys. The resulting map will contain all keys, even if some of the keys in the slice passed as parameter were not present in the cache. |
| GetAll | Gets all cache entries. |
Expand Down Expand Up @@ -247,74 +249,62 @@ but if you're looking into using a library like gocache, odds are, you want more

### Results
| key | value |
|:------ |:-------- |
|:-------|:---------|
| goos | windows |
| goarch | amd64 |
| cpu | i7-9700K |
| mem | 32G DDR4 |

```
// Normal map
BenchmarkMap_Get
BenchmarkMap_Get-8 46087372 26.7 ns/op
BenchmarkMap_Set
BenchmarkMap_Set/small_value-8 3841911 389 ns/op
BenchmarkMap_Set/medium_value-8 3887074 391 ns/op
BenchmarkMap_Set/large_value-8 3921956 393 ns/op
// Gocache
BenchmarkCache_Get
BenchmarkCache_Get/FirstInFirstOut-8 27273036 46.4 ns/op
BenchmarkCache_Get/LeastRecentlyUsed-8 26648248 46.3 ns/op
BenchmarkCache_Set
BenchmarkCache_Set/FirstInFirstOut_small_value-8 2919584 405 ns/op
BenchmarkCache_Set/FirstInFirstOut_medium_value-8 2990841 391 ns/op
BenchmarkCache_Set/FirstInFirstOut_large_value-8 2970513 391 ns/op
BenchmarkCache_Set/LeastRecentlyUsed_small_value-8 2962939 402 ns/op
BenchmarkCache_Set/LeastRecentlyUsed_medium_value-8 2962963 390 ns/op
BenchmarkCache_Set/LeastRecentlyUsed_large_value-8 2962928 394 ns/op
BenchmarkCache_SetUsingMaxMemoryUsage
BenchmarkCache_SetUsingMaxMemoryUsage/small_value-8 2683356 447 ns/op
BenchmarkCache_SetUsingMaxMemoryUsage/medium_value-8 2637578 441 ns/op
BenchmarkCache_SetUsingMaxMemoryUsage/large_value-8 2672434 443 ns/op
BenchmarkCache_SetWithMaxSize
BenchmarkCache_SetWithMaxSize/100_small_value-8 4782966 252 ns/op
BenchmarkCache_SetWithMaxSize/10000_small_value-8 4067967 296 ns/op
BenchmarkCache_SetWithMaxSize/100000_small_value-8 3762055 328 ns/op
BenchmarkCache_SetWithMaxSize/100_medium_value-8 4760479 252 ns/op
BenchmarkCache_SetWithMaxSize/10000_medium_value-8 4081050 295 ns/op
BenchmarkCache_SetWithMaxSize/100000_medium_value-8 3785050 330 ns/op
BenchmarkCache_SetWithMaxSize/100_large_value-8 4732909 254 ns/op
BenchmarkCache_SetWithMaxSize/10000_large_value-8 4079533 297 ns/op
BenchmarkCache_SetWithMaxSize/100000_large_value-8 3712820 331 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU
BenchmarkCache_SetWithMaxSizeAndLRU/100_small_value-8 4761732 254 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_small_value-8 4084474 296 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_small_value-8 3761402 329 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/100_medium_value-8 4783075 254 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_medium_value-8 4103980 296 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_medium_value-8 3646023 331 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/100_large_value-8 4779025 254 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_large_value-8 4096192 296 ns/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_large_value-8 3726823 331 ns/op
BenchmarkCache_GetSetMultipleConcurrent
BenchmarkCache_GetSetMultipleConcurrent-8 707142 1698 ns/op
BenchmarkCache_GetSetConcurrentWithFrequentEviction
BenchmarkCache_GetSetConcurrentWithFrequentEviction/FirstInFirstOut-8 3616256 334 ns/op
BenchmarkCache_GetSetConcurrentWithFrequentEviction/LeastRecentlyUsed-8 3636367 331 ns/op
BenchmarkCache_GetConcurrentWithLRU
BenchmarkCache_GetConcurrentWithLRU/FirstInFirstOut-8 4405557 268 ns/op
BenchmarkCache_GetConcurrentWithLRU/LeastRecentlyUsed-8 4445475 269 ns/op
BenchmarkCache_WithForceNilInterfaceOnNilPointer
BenchmarkCache_WithForceNilInterfaceOnNilPointer/true_with_nil_struct_pointer-8 6184591 191 ns/op
BenchmarkCache_WithForceNilInterfaceOnNilPointer/true-8 6090482 191 ns/op
BenchmarkCache_WithForceNilInterfaceOnNilPointer/false_with_nil_struct_pointer-8 6184629 187 ns/op
BenchmarkCache_WithForceNilInterfaceOnNilPointer/false-8 6281781 186 ns/op
(Trimmed "BenchmarkCache_" for readability)
WithForceNilInterfaceOnNilPointerWithConcurrency
WithForceNilInterfaceOnNilPointerWithConcurrency/true_with_nil_struct_pointer-8 4379564 268 ns/op
WithForceNilInterfaceOnNilPointerWithConcurrency/true-8 4379558 265 ns/op
WithForceNilInterfaceOnNilPointerWithConcurrency/false_with_nil_struct_pointer-8 4444456 261 ns/op
WithForceNilInterfaceOnNilPointerWithConcurrency/false-8 4493896 262 ns/op
BenchmarkMap_Get-8 49944228 24.2 ns/op 7 B/op 0 allocs/op
BenchmarkMap_Set/small_value-8 3939964 394.1 ns/op 188 B/op 2 allocs/op
BenchmarkMap_Set/medium_value-8 3868586 395.5 ns/op 191 B/op 2 allocs/op
BenchmarkMap_Set/large_value-8 3992138 385.3 ns/op 186 B/op 2 allocs/op
// Gocache
BenchmarkCache_Get/FirstInFirstOut-8 27907950 44.3 ns/op 7 B/op 0 allocs/op
BenchmarkCache_Get/LeastRecentlyUsed-8 28211396 44.2 ns/op 7 B/op 0 allocs/op
BenchmarkCache_Set/FirstInFirstOut_small_value-8 3139538 373.5 ns/op 185 B/op 3 allocs/op
BenchmarkCache_Set/FirstInFirstOut_medium_value-8 3099516 378.6 ns/op 186 B/op 3 allocs/op
BenchmarkCache_Set/FirstInFirstOut_large_value-8 3086776 386.7 ns/op 186 B/op 3 allocs/op
BenchmarkCache_Set/LeastRecentlyUsed_small_value-8 3070555 379.0 ns/op 187 B/op 3 allocs/op
BenchmarkCache_Set/LeastRecentlyUsed_medium_value-8 3056928 383.8 ns/op 187 B/op 3 allocs/op
BenchmarkCache_Set/LeastRecentlyUsed_large_value-8 3108250 383.8 ns/op 186 B/op 3 allocs/op
BenchmarkCache_SetUsingMaxMemoryUsage/medium_value-8 2773315 449.0 ns/op 210 B/op 4 allocs/op
BenchmarkCache_SetUsingMaxMemoryUsage/large_value-8 2731818 440.0 ns/op 211 B/op 4 allocs/op
BenchmarkCache_SetUsingMaxMemoryUsage/small_value-8 2659296 446.8 ns/op 213 B/op 4 allocs/op
BenchmarkCache_SetWithMaxSize/100_small_value-8 4848658 248.8 ns/op 114 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/10000_small_value-8 4117632 293.7 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/100000_small_value-8 3867402 313.0 ns/op 110 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/100_medium_value-8 4750057 250.1 ns/op 113 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/10000_medium_value-8 4143772 294.5 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/100000_medium_value-8 3768883 313.2 ns/op 111 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/100_large_value-8 4822646 251.1 ns/op 114 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/10000_large_value-8 4154428 291.6 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSize/100000_large_value-8 3897358 313.7 ns/op 110 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100_small_value-8 4784180 254.2 ns/op 114 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_small_value-8 4067042 292.0 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_small_value-8 3832760 313.8 ns/op 111 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100_medium_value-8 4846706 252.2 ns/op 114 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_medium_value-8 4103817 292.5 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_medium_value-8 3845623 315.1 ns/op 111 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100_large_value-8 4744513 257.9 ns/op 114 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/10000_large_value-8 3956316 299.5 ns/op 106 B/op 3 allocs/op
BenchmarkCache_SetWithMaxSizeAndLRU/100000_large_value-8 3876843 351.3 ns/op 110 B/op 3 allocs/op
BenchmarkCache_GetSetMultipleConcurrent-8 750088 1566.0 ns/op 128 B/op 8 allocs/op
BenchmarkCache_GetSetConcurrentWithFrequentEviction/FirstInFirstOut-8 3836961 316.2 ns/op 80 B/op 1 allocs/op
BenchmarkCache_GetSetConcurrentWithFrequentEviction/LeastRecentlyUsed-8 3846165 315.6 ns/op 80 B/op 1 allocs/op
BenchmarkCache_GetConcurrently/FirstInFirstOut-8 4830342 239.8 ns/op 8 B/op 1 allocs/op
BenchmarkCache_GetConcurrently/LeastRecentlyUsed-8 4895587 243.2 ns/op 8 B/op 1 allocs/op
(Trimmed "BenchmarkCache_" for readability)
WithForceNilInterfaceOnNilPointer/true_with_nil_struct_pointer-8 6901461 178.5 ns/op 7 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointer/true-8 6629566 180.7 ns/op 7 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointer/false_with_nil_struct_pointer-8 6282798 170.1 ns/op 7 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointer/false-8 6741382 172.6 ns/op 7 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointerWithConcurrency/true_with_nil_struct_pointer-8 4432951 258.0 ns/op 8 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointerWithConcurrency/true-8 4676943 244.4 ns/op 8 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointerWithConcurrency/false_with_nil_struct_pointer-8 4818418 239.6 ns/op 8 B/op 1 allocs/op
WithForceNilInterfaceOnNilPointerWithConcurrency/false-8 5025937 238.2 ns/op 8 B/op 1 allocs/op
```


Expand Down
27 changes: 25 additions & 2 deletions gocache.go
Expand Up @@ -37,6 +37,8 @@ var (
)

// Cache is the core struct of gocache which contains the data as well as all relevant configuration fields
//
// Do not instantiate this struct directly, use NewCache instead
type Cache struct {
// maxSize is the maximum amount of entries that can be in the cache at any given time
// By default, this is set to DefaultMaxSize
Expand All @@ -50,6 +52,10 @@ type Cache struct {
// evictionPolicy is the eviction policy
evictionPolicy EvictionPolicy

// defaultTTL is the default TTL for each entry
// Defaults to NoExpiration
defaultTTL time.Duration

// stats is the object that contains cache statistics/metrics
stats *Statistics

Expand Down Expand Up @@ -143,12 +149,23 @@ func (cache *Cache) WithMaxMemoryUsage(maxMemoryUsageInBytes int) *Cache {
}

// WithEvictionPolicy sets eviction algorithm.
//
// Defaults to FirstInFirstOut (FIFO)
func (cache *Cache) WithEvictionPolicy(policy EvictionPolicy) *Cache {
cache.evictionPolicy = policy
return cache
}

// WithDefaultTTL sets the default TTL for each entry (unless a different TTL is specified using SetWithTTL or SetAllWithTTL)
//
// Defaults to NoExpiration (-1)
func (cache *Cache) WithDefaultTTL(ttl time.Duration) *Cache {
if ttl > 1 {
cache.defaultTTL = ttl
}
return cache
}

// WithForceNilInterfaceOnNilPointer sets whether all Set-like functions should set a value as nil if the
// interface passed has a nil value but not a nil type.
//
Expand Down Expand Up @@ -202,6 +219,7 @@ func NewCache() *Cache {
return &Cache{
maxSize: DefaultMaxSize,
evictionPolicy: FirstInFirstOut,
defaultTTL: NoExpiration,
stats: &Statistics{},
entries: make(map[string]*Entry),
mutex: sync.RWMutex{},
Expand All @@ -212,7 +230,7 @@ func NewCache() *Cache {

// Set creates or updates a key with a given value
func (cache *Cache) Set(key string, value any) {
cache.SetWithTTL(key, value, NoExpiration)
cache.SetWithTTL(key, value, cache.defaultTTL)
}

// SetWithTTL creates or updates a key with a given value and sets an expiration time (-1 is NoExpiration)
Expand Down Expand Up @@ -301,8 +319,13 @@ func (cache *Cache) SetWithTTL(key string, value any, ttl time.Duration) {

// SetAll creates or updates multiple values
func (cache *Cache) SetAll(entries map[string]any) {
cache.SetAllWithTTL(entries, cache.defaultTTL)
}

// SetAllWithTTL creates or updates multiple values
func (cache *Cache) SetAllWithTTL(entries map[string]any, ttl time.Duration) {
for key, value := range entries {
cache.SetWithTTL(key, value, NoExpiration)
cache.SetWithTTL(key, value, ttl)
}
}

Expand Down