GitHub - floatdrop/lru: Thread safe GoLang LRU cache (original) (raw)
lru
Thread safe GoLang LRU cache.
Example
import ( "fmt"
"github.com/floatdrop/lru")
func main() { cache := lru.Newstring, int
cache.Set("Hello", 5)
if e := cache.Get("Hello"); e != nil {
fmt.Println(*e)
// Output: 5
}}
TTL
You can wrap values into Expiring[T any] struct to release memory on timer (or manually in Valid method).
Example implementation
import ( "fmt" "time"
"github.com/floatdrop/lru")
type Expiring[T any] struct { value *T }
func (E *Expiring[T]) Valid() *T { if E == nil { return nil }
return E.value}
func WithTTL[T any](value T, ttl time.Duration) Expiring[T] { e := Expiring[T]{ value: &value, }
time.AfterFunc(ttl, func() {
e.value = nil // Release memory
})
return e}
func main() { l := lru.Newstring, Expiring[string]
l.Set("Hello", WithTTL("Bye", time.Hour))
if e := l.Get("Hello").Valid(); e != nil {
fmt.Println(*e)
}}
Note: Althou this short implementation frees memory after ttl duration, it will not erase entry for key in cache. It can be a problem, if you do not check nillnes after getting element from cache and call Set afterwards.
Benchmarks
floatdrop/lru:
BenchmarkLRU_Rand-8 8802915 131.7 ns/op 24 B/op 1 allocs/op
BenchmarkLRU_Freq-8 9392769 127.8 ns/op 24 B/op 1 allocs/op
hashicorp/golang-lru:
BenchmarkLRU_Rand-8 5992782 195.8 ns/op 76 B/op 3 allocs/op
BenchmarkLRU_Freq-8 6355358 186.1 ns/op 71 B/op 3 allocs/op
jellydator/ttlcache:
BenchmarkLRU_Rand-8 4447654 253.5 ns/op 144 B/op 2 allocs/op
BenchmarkLRU_Freq-8 4837938 240.9 ns/op 137 B/op 2 allocs/op