Documentation
¶
Overview ¶
Package evict is a family of fixed-capacity in-memory caches that share one API and differ in how they choose what to evict:
- github.com/floatdrop/evict/lru evicts the least recently used entry.
- github.com/floatdrop/evict/twoq implements 2Q, which keeps new entries apart from the ones that came back after they had been evicted, so that a burst of new entries cannot push out the proven ones.
- github.com/floatdrop/evict/sieve implements SIEVE, a queue with lazy promotion, and reads from it without taking a lock.
- github.com/floatdrop/evict/s3fifo implements S3-FIFO, which lets new entries prove themselves in a small queue before they get into the main one, and reads without taking a lock as well.
- github.com/floatdrop/evict/tinylfu admits with TinyLFU: an entry gets past the small queue only if its key has been asked for more often of late than the entry it would replace, by a record that the cache keeps of keys whether it holds them or not. It finds the size of the small queue by itself, and reads without taking a lock as well.
Every cache is safe for concurrent use and keeps its entries in arrays that it allocates when it is created and addresses by 32-bit indices. Getting, setting and deleting entries therefore allocates nothing, and the garbage collector has nothing to trace beyond the keys and values themselves.
There is one thing the caches cannot help: to hash a key that is a pointer or an interface, or that contains one, Go moves the key to the heap if it is not there already. Strings do not count. A lookup with such a key that was made up on the spot, like a number put into an interface, costs an allocation that a map would have avoided.
Keys are compared with ==, as in a map. A key that is not equal to itself, which is to say one with a NaN in it, can be set but not found again: its entry is out of reach until it is evicted or the cache is cleared.
Capacity and shards ¶
A cache spreads its entries over shards by the hash of their keys, so that goroutines working on different shards do not wait for each other. Every shard has its share of the capacity and evicts on its own: a shard that is full evicts although the cache as a whole may have room. The capacity is therefore an upper bound that a cache with several shards rarely reaches exactly. Small caches have a single shard, for which it is exact, and the WithShards option of each package sets the number for the others.
This package holds what the caches have in common: the Cache interface. github.com/floatdrop/evict/stats counts the hits, misses and evictions of any of them.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache[K comparable, V any] interface { // Get returns the value stored under key and records the access with // the eviction policy. Get(key K) (value V, ok bool) // Peek returns the value stored under key without telling the eviction // policy about it. Peek(key K) (value V, ok bool) // Set stores value under key and reports the entry that left the cache // as a result, if there is one. That entry is either the previous entry // for key, in which case oldKey == key, or an entry that was evicted to // make room. A cache with no capacity keeps nothing and hands the new // entry straight back. // // Whatever an entry holds on to can thus be released when Set returns // it, whichever way it left. That goes for the key as well: when an // entry is replaced, the cache keeps the key it was just given and // returns the one it had. Set(key K, value V) (oldKey K, oldValue V, displaced bool) // Delete removes key and returns the value it had. Delete(key K) (value V, ok bool) // Len returns the number of entries in the cache. While the cache is // being written to, the shards are counted one after the other and // the sum may be one that the cache never held at any one moment. Len() int // Cap returns the number of entries the cache can hold. Cap() int // Clear removes every entry, without reporting any of them. If the // entries hold on to something that has to be released, do that by // going over them with All before Clear, at a time when nothing else // is using the cache: an entry that is added in between would be // cleared unseen, and one that is replaced would be seen twice, by // the loop and by whoever replaced it. Clear() // All iterates over the entries in no particular order, without // recording accesses. It copies the entries of one shard at a time, // which is the one operation on a cache that allocates. // // The cache may be used, also by the loop body, while the iteration is // in progress. Entries that are added or removed in the meantime may // or may not be seen; no entry is seen twice unless it is removed and // added again. All() iter.Seq2[K, V] }
Cache is the behaviour common to every cache in this module. It is implemented by *lru.Cache, *twoq.Cache, *sieve.Cache, *s3fifo.Cache and *tinylfu.Cache.
All methods are safe for concurrent use.
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
cachetest
Package cachetest holds the tests that every cache in this module has to pass, whatever its eviction policy.
|
Package cachetest holds the tests that every cache in this module has to pass, whatever its eviction policy. |
|
cslab
Package cslab is the concurrent sibling of package slab.
|
Package cslab is the concurrent sibling of package slab. |
|
ghost
Package ghost provides the memory of a cache for keys it no longer holds: a set that remembers what was added to it for a while and then forgets it.
|
Package ghost provides the memory of a cache for keys it no longer holds: a set that remembers what was added to it for a while and then forgets it. |
|
inlinecheck/probe/lru
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module.
|
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module. |
|
inlinecheck/probe/s3fifo
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module.
|
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module. |
|
inlinecheck/probe/sieve
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module.
|
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module. |
|
inlinecheck/probe/stats
Package probe uses a counted cache the way a program does: with key and value types of its own, and without importing anything but the counter, not even a cache of this module.
|
Package probe uses a counted cache the way a program does: with key and value types of its own, and without importing anything but the counter, not even a cache of this module. |
|
inlinecheck/probe/statswrap
Package probe is a generic type that wraps a counted cache and instantiates nothing, like a program's own cache type might.
|
Package probe is a generic type that wraps a counted cache and instantiates nothing, like a program's own cache type might. |
|
inlinecheck/probe/statswrapuser
Package probe uses a counted cache through statswrap, a generic type of another package that instantiates nothing.
|
Package probe uses a counted cache through statswrap, a generic type of another package that instantiates nothing. |
|
inlinecheck/probe/tinylfu
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module.
|
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module. |
|
inlinecheck/probe/twoq
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module.
|
Package probe uses a cache the way a program does: with key and value types of its own, and without importing anything else, not even another cache of this module. |
|
inlinecheck/probe/wrap
Package wrap holds the caches that read without a lock in a generic type of its own, as a program may, and instantiates nothing.
|
Package wrap holds the caches that read without a lock in a generic type of its own, as a program may, and instantiates nothing. |
|
inlinecheck/probe/wrapuser
Package wrapuser uses the caches through package wrap, with key and value types of its own, and imports nothing else.
|
Package wrapuser uses the caches through package wrap, with key and value types of its own, and imports nothing else. |
|
shards
Package shards holds the arithmetic for splitting a cache into shards, each with its own lock and its own share of the capacity.
|
Package shards holds the arithmetic for splitting a cache into shards, each with its own lock and its own share of the capacity. |
|
sketch
Package sketch provides the memory that a cache has of how often keys have been asked for of late, whether it holds them or not: the frequency sketch of TinyLFU.
|
Package sketch provides the memory that a cache has of how often keys have been asked for of late, whether it holds them or not: the frequency sketch of TinyLFU. |
|
slab
Package slab provides the storage shared by the caches in this module that do all of their work under a lock: a fixed array of entries addressed by 32-bit indices, an open-addressing hash index over those entries, and intrusive doubly linked lists threaded through them.
|
Package slab provides the storage shared by the caches in this module that do all of their work under a lock: a fixed array of entries addressed by 32-bit indices, an open-addressing hash index over those entries, and intrusive doubly linked lists threaded through them. |
|
Package lru provides a fixed-capacity cache that evicts the least recently used entry.
|
Package lru provides a fixed-capacity cache that evicts the least recently used entry. |
|
Package s3fifo provides a fixed-capacity cache that evicts with S3-FIFO and whose reads take no lock.
|
Package s3fifo provides a fixed-capacity cache that evicts with S3-FIFO and whose reads take no lock. |
|
Package sieve provides a fixed-capacity cache that evicts with SIEVE and whose reads take no lock.
|
Package sieve provides a fixed-capacity cache that evicts with SIEVE and whose reads take no lock. |
|
Package stats counts the hits, misses and evictions of a cache, so that it can be monitored.
|
Package stats counts the hits, misses and evictions of a cache, so that it can be monitored. |
|
Package tinylfu provides a fixed-capacity cache that admits with TinyLFU and whose reads take no lock.
|
Package tinylfu provides a fixed-capacity cache that admits with TinyLFU and whose reads take no lock. |
|
Package twoq provides a fixed-capacity cache that evicts with 2Q.
|
Package twoq provides a fixed-capacity cache that evicts with 2Q. |