Documentation
¶
Overview ¶
Package lru provides generic type and concurrent safe LRU data structures with near O(1) perf and optional time-based expiration support.
Example (BasicMapUsage) ¶
This example demonstrates creating a new map instance, inserting items into the map, existence checking, looking up an item, causing an eviction of the least recently used item, and removing an item.
package main import ( "fmt" "github.com/decred/dcrd/container/lru" ) func main() { // Create a new map instance with the desired limit and no time-based // expiration of items. const maxItems = 10 m := lru.NewMap[int, int](maxItems) // Insert items into the map. for i := 0; i < maxItems; i++ { m.Put(i, (i+1)*100) } // At this point, the map has reached the limit, so the first entry will // still be a member. if !m.Exists(0) { fmt.Println("map does not contain expected item 0") return } // Lookup an item. if v, ok := m.Get(0); !ok || v != 100 { fmt.Println("map does not contain expected value for item 0") return } // Inserting another item will evict the least recently used item, which // will be the item with key 1 since 0 was just accessed above. const oneOverMax = maxItems + 1 numEvicted := m.Put(oneOverMax, oneOverMax) if numEvicted != 1 { fmt.Printf("expected one evicted item, but got %d", numEvicted) return } if m.Exists(1) { fmt.Println("map contains unexpected item 1") return } // Remove an item. m.Delete(3) if m.Exists(3) { fmt.Println("map contains unexpected item 3") return } }
Example (BasicSetUsage) ¶
This example demonstrates creating a new set instance, inserting items into the set, checking set containment, causing an eviction of the least recently used item, and removing an item.
package main import ( "fmt" "github.com/decred/dcrd/container/lru" ) func main() { // Create a new set instance with the desired limit and no time-based // expiration of items. const maxItems = 10 set := lru.NewSet[int](maxItems) // Insert items into the set. for i := 0; i < maxItems; i++ { set.Put(i) } // At this point, the set has reached the limit, so the first entry will // still be a member. Note that Exists does not update any state so it // will not modify the eviction priority or the hit ratio. if !set.Exists(0) { fmt.Println("set does not contain expected item 0") return } // Check set containment. This modifies the priority to be the most // recently used item so it will be evicted last. if !set.Contains(0) { fmt.Println("set does not contain expected item 0") return } // Inserting another item will evict the least recently used item, which // will be the item 1 since item 0 was just accessed via Contains. numEvicted := set.Put(maxItems + 1) if numEvicted != 1 { fmt.Printf("expected one evicted item, but got %d", numEvicted) return } if set.Exists(1) { fmt.Println("set contains unexpected item 1") return } // Remove an item. set.Delete(3) if set.Exists(3) { fmt.Println("set contains unexpected item 3") return } }
Index ¶
- type Map
- func (m *Map[K, V]) Clear()
- func (m *Map[K, V]) Delete(key K)
- func (m *Map[K, V]) EvictExpiredNow() (numEvicted uint32)
- func (m *Map[K, V]) Exists(key K) bool
- func (m *Map[K, V]) Get(key K) (V, bool)
- func (m *Map[K, V]) HitRatio() float64
- func (m *Map[K, V]) Keys() []K
- func (m *Map[K, V]) Len() uint32
- func (m *Map[K, V]) Peek(key K) (V, bool)
- func (m *Map[K, V]) Put(key K, value V) (numEvicted uint32)
- func (m *Map[K, V]) PutWithTTL(key K, value V, ttl time.Duration) (numEvicted uint32)
- func (m *Map[K, V]) Values() []V
- type Set
- func (c *Set[T]) Clear()
- func (c *Set[T]) Contains(item T) bool
- func (c *Set[T]) Delete(item T)
- func (c *Set[T]) EvictExpiredNow() (numEvicted uint32)
- func (c *Set[T]) Exists(item T) bool
- func (c *Set[T]) HitRatio() float64
- func (c *Set[T]) Items() []T
- func (c *Set[T]) Len() uint32
- func (c *Set[T]) Put(item T) (numEvicted uint32)
- func (c *Set[T]) PutWithTTL(item T, ttl time.Duration) (numEvicted uint32)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Map ¶
type Map[K comparable, V any] struct { // contains filtered or unexported fields }
Map provides a concurrency safe least recently used (LRU) map with nearly O(1) lookups, inserts, and deletions. The map is limited to a maximum number of items with eviction of the least recently used entry when the limit is exceeded.
It also supports optional item expiration after a configurable time to live (TTL) with periodic lazy removal. NewMap provides no item expiration by default while NewMapWithDefaultTTL provides a configurable TTL that is applied to all items by default. In both cases, callers may override the default TTL of individual items via [PutWithTTL].
Expiration TTLs are relative to the time an item is added or updated via [Put] or [PutWithTTL]. Accessing items does not extend the TTL.
An efficient lazy removal scheme is used such that expired items are periodically removed when items are added or updated via [Put] or [PutWithTTL]. In other words, expired items may physically remain in the map until the next expiration scan is triggered, however, they will no longer publicly appear as members of the map. This approach allows for efficient amortized removal of expired items without the need for additional background tasks or timers.
Callers may optionally use [EvictExpiredNow] to immediately remove all items that are marked expired without waiting for the next expiration scan in cases where more deterministic expiration is required.
NewMap or NewMapWithDefaultTTL must be used to create a usable map since the zero value of this struct is not valid.
func NewMap ¶
func NewMap[K comparable, V any](limit uint32) *Map[K, V]
NewMap returns an initialized and empty LRU map where no items will expire by default.
The provided limit is the maximum number of items the map will hold before it evicts least recently used items to make room for new items.
See NewMapWithDefaultTTL for a variant that allows a configurable time to live to be applied to all items by default.
See the documentation for Map for more details.
func NewMapWithDefaultTTL ¶
NewMapWithDefaultTTL returns an initialized and empty LRU map where the provided non-zero time to live (TTL) is applied to all items by default.
A TTL of zero disables item expiration by default and is equivalent to NewMap.
See NewMap for a variant that does not expire any items by default.
See the documentation for Map for more details.
func (*Map[K, V]) Clear ¶
func (m *Map[K, V]) Clear()
Clear removes all items and resets the hit ratio.
This function is safe for concurrent access.
func (*Map[K, V]) Delete ¶
func (m *Map[K, V]) Delete(key K)
Delete deletes the item associated with the passed key if it exists.
This function is safe for concurrent access.
func (*Map[K, V]) EvictExpiredNow ¶
EvictExpiredNow immediately removes all items that are marked expired without waiting for the next expiration scan. It returns the number of items that were removed.
It is expected that most callers will typically use the automatic lazy expiration behavior and thus have no need to call this method. However, it is provided in case more deterministic expiration is required.
Example ¶
This example demonstrates creating a new map instance with time-based expiration, inserting items into it, and manually triggering removal of expired items.
package main import ( "fmt" "time" "github.com/decred/dcrd/container/lru" ) func main() { // Create a new map instance with the desired limit and a time-based // expiration of items for one millisecond. Callers would typically want to // use much longer durations. const maxItems = 10 const ttl = time.Millisecond m := lru.NewMapWithDefaultTTL[string, string](maxItems, ttl) // Insert an item, wait for the item to expire, and remove expired items. // // Ordinarily, callers do not need to explicitly call the removal method // since expired items are periodically removed as items are added and // updated. However, it is done here for the purposes of the example. const key = "foo" m.Put(key, "bar") time.Sleep(ttl * 2) numEvicted := m.EvictExpiredNow() if numEvicted != 1 { fmt.Printf("expected one evicted item, but got %d", numEvicted) return } if m.Exists(key) { fmt.Printf("map contains unexpected expired item %q\n", key) return } }
func (*Map[K, V]) Exists ¶
Exists returns whether or not the passed item is a member. The priority and expiration time for the item are not modified. It does not affect the hit ratio.
This function is safe for concurrent access.
func (*Map[K, V]) Get ¶
Get returns the value associated with the passed key if it is a member and modifies its priority to be the most recently used item. The expiration time for the item is not modified.
The boolean return value indicates whether or not the item lookup was successful.
See [Peek] for a variant that does not modify the priority or update the hit ratio.
This function is safe for concurrent access.
func (*Map[K, V]) HitRatio ¶
HitRatio returns the percentage of lookups via [Get] that resulted in a successful hit.
This function is safe for concurrent access.
func (*Map[K, V]) Keys ¶
func (m *Map[K, V]) Keys() []K
Keys returns a slice of unexpired keys ordered from least recently used to most recently used. The priority and expiration times for the items are not modified.
This function is safe for concurrent access.
func (*Map[K, V]) Len ¶
Len returns the number of items in the map.
This function is safe for concurrent access.
func (*Map[K, V]) Peek ¶
Peek returns the associated value of the passed key if it is a member without modifying any priority or the hit ratio. The boolean return value indicates whether or not the item lookup is successful.
This function is safe for concurrent access.
func (*Map[K, V]) Put ¶
Put either adds the passed key/value pair when an item for that key does not already exist or updates the existing item for the given key to the passed value and arranges for the item to expire after the configured default TTL (if any). The associated item becomes the most recently used item.
The least recently used item is evicted when adding a new item would exceed the max limit.
It returns the number of evicted items which includes any items that were evicted due to being marked expired.
See [PutWithTTL] for a variant that allows setting a specific TTL for the item.
This function is safe for concurrent access.
func (*Map[K, V]) PutWithTTL ¶
PutWithTTL either adds the passed key/value pair when an item for that key does not already exist or updates the existing item for the given key to the passed value and arranges for the item to expire after the provided time to live (TTL). The associated item becomes the most recently used item.
The least recently used item is evicted when adding a new item would exceed the max limit.
A TTL of zero will disable expiration for the item. This can be useful to disable the expiration for specific items when the map was configured with a default expiration TTL.
It returns the number of evicted items which includes any items that were evicted due to being marked expired.
This function is safe for concurrent access.
type Set ¶
type Set[T comparable] struct { // contains filtered or unexported fields }
Set provides a concurrency safe least recently used (LRU) set with nearly O(1) lookups, inserts, and deletions. The set is limited to a maximum number of items with eviction of the least recently used entry when the limit is exceeded.
It also supports optional item expiration after a configurable time to live (TTL) with periodic lazy removal. NewSet provides no item expiration by default while NewSetWithDefaultTTL provides a configurable TTL that is applied to all items by default. In both cases, callers may override the default TTL of individual items via [PutWithTTL].
Expiration TTLs are relative to the time an item is added or updated via [Put] or [PutWithTTL]. Accessing items does not extend the TTL.
An efficient lazy removal scheme is used such that expired items are periodically removed when items are added or updated via [Put] or [PutWithTTL]. In other words, expired items may physically remain in the set until the next expiration scan is triggered, however, they will no longer publicly appear as members of the set. This approach allows for efficient amortized removal of expired items without the need for additional background tasks or timers.
Callers may optionally use [EvictExpiredNow] to immediately remove all items that are marked expired without waiting for the next expiration scan in cases where more deterministic expiration is required.
NewSet or NewSetWithDefaultTTL must be used to create a usable set since the zero value of this struct is not valid.
func NewSet ¶
func NewSet[T comparable](limit uint32) *Set[T]
NewSet returns an initialized and empty LRU set where no items will expire by default.
The provided limit is the maximum number of items the set will hold before it evicts least recently used items to make room for new items.
See NewSetWithDefaultTTL for a variant that allows a configurable time to live to be applied to all items by default.
See the documentation for Set for more details.
func NewSetWithDefaultTTL ¶
func NewSetWithDefaultTTL[T comparable](limit uint32, ttl time.Duration) *Set[T]
NewSetWithDefaultTTL returns an initialized and empty LRU set where the provided non-zero time to live (TTL) is applied to all items by default.
A TTL of zero disables item expiration by default and is equivalent to NewSet.
See NewSet for a variant that does not expire any items by default.
See the documentation for Set for more details.
func (*Set[T]) Clear ¶
func (c *Set[T]) Clear()
Clear removes all items and resets the hit ratio.
This function is safe for concurrent access.
func (*Set[T]) Contains ¶
Contains returns whether or not the passed item is a member and modifies its priority to be the most recently used item when it is. The expiration time for the item is not modified. The hit ratio is updated accordingly.
See [Exists] for a variant that does not modify the priority of the item or update the hit ratio.
This function is safe for concurrent access.
func (*Set[T]) Delete ¶
func (c *Set[T]) Delete(item T)
Delete deletes the passed item if it exists.
This function is safe for concurrent access.
func (*Set[T]) EvictExpiredNow ¶
EvictExpiredNow immediately removes all items that are marked expired without waiting for the next expiration scan. It returns the number of items that were removed.
It is expected that most callers will typically use the automatic lazy expiration behavior and thus have no need to call this method. However, it is provided in case more deterministic expiration is required.
func (*Set[T]) Exists ¶
Exists returns whether or not the passed item is a member. The priority and expiration time for the item are not modified. It does not affect the hit ratio.
See [Contains] for a variant that modifies the priority of the item to be the most recently used item when it exists and updates the hit ratio accordingly.
This function is safe for concurrent access.
func (*Set[T]) HitRatio ¶
HitRatio returns the percentage of lookups via [Contains] that resulted in a successful hit.
This function is safe for concurrent access.
func (*Set[T]) Items ¶
func (c *Set[T]) Items() []T
Items returns a slice of unexpired items ordered from least recently used to most recently used. The priority and expiration times for the items are not modified.
This function is safe for concurrent access.
func (*Set[T]) Len ¶
Len returns the number of items in the set.
This function is safe for concurrent access.
func (*Set[T]) Put ¶
Put either adds the passed item when it does not already exist or refreshes the existing item and arranges for the item to expire after the configured default TTL (if any). The item becomes the most recently used item.
The least recently used item is evicted when adding a new item would exceed the max limit.
It returns the number of evicted items which includes any items that were evicted due to being marked expired.
See [PutWithTTL] for a variant that allows configuring a specific TTL for the item.
This function is safe for concurrent access.
func (*Set[T]) PutWithTTL ¶
PutWithTTL either adds the passed item when it does not already exist or refreshes the existing item and arranges for the item to expire after the provided time to live (TTL). The item becomes the most recently used item.
The least recently used item is evicted when adding a new item would exceed the max limit.
A TTL of zero will disable expiration for the item. This can be useful to disable the TTL for specific items when the set was configured with a default expiration TTL.
It returns the number of evicted items which includes any items that were evicted due to being marked expired.
This function is safe for concurrent access.
Example ¶
This example demonstrates per-item expiration by creating a new set instance with no time-based expiration, inserting items into it, updating one of the items to have a timeout, and manually triggering removal of expired item.
package main import ( "fmt" "time" "github.com/decred/dcrd/container/lru" ) func main() { // Create a new set instance with the desired limit and no time-based // expiration of items. const maxItems = 10 set := lru.NewSet[int](maxItems) // Insert items into the set. for i := 0; i < maxItems; i++ { set.Put(i) } // Update item 1 to expire after one millisecond, wait for the item to // expire, and remove expired items. Callers would typically want to use // much longer durations. // // Since all of the other items are not set to expire by default, only the // single item updated to have a TTL will be expired. // // Ordinarily, callers do not need to explicitly call the removal method // since expired items are periodically removed as items are added and // updated. However, it is done here for the purposes of the example. const ttl = time.Millisecond numEvicted := set.PutWithTTL(1, ttl) if numEvicted != 0 { fmt.Printf("expected no evicted items, but got %d", numEvicted) return } time.Sleep(ttl * 2) numEvicted = set.EvictExpiredNow() if numEvicted != 1 { fmt.Printf("expected one evicted item, but got %d", numEvicted) return } }