Documentation
¶
Overview ¶
Package v2 provides a high-performance concurrent map implementation optimized for cache operations. The implementation uses sharding to minimize lock contention by dividing the map into multiple independent shards, each protected by its own read-write mutex.
The concurrent map stores string keys mapped to *cache.Item values and is designed to be thread-safe for concurrent read and write operations across multiple goroutines.
Key features:
- Sharded design with 32 shards to reduce lock contention
- FNV-1a hash function for efficient key distribution
- Thread-safe operations with optimized read/write locking
- iter.Seq2 iteration via All() for safe concurrent traversal
- Standard map operations: Set, Get, Has, Remove, Pop, Clear, Count
Example usage:
cm := v2.New()
cm.Set("key", &cache.Item{...})
if item, ok := cm.Get("key"); ok {
// Process item
}
Index ¶
- Constants
- func Hash(key string) uint32
- type ConcurrentMap
- func (cm *ConcurrentMap) All() iter.Seq2[string, *Item]
- func (cm *ConcurrentMap) Clear()
- func (cm *ConcurrentMap) Count() int
- func (cm *ConcurrentMap) Get(key string) (*Item, bool)
- func (cm *ConcurrentMap) GetCopy(key string) (*Item, bool)
- func (cm *ConcurrentMap) GetShard(key string) *ConcurrentMapShard
- func (cm *ConcurrentMap) Has(key string) bool
- func (cm *ConcurrentMap) Pop(key string) (*Item, bool)
- func (cm *ConcurrentMap) Remove(key string)
- func (cm *ConcurrentMap) Set(key string, value *Item)
- func (cm *ConcurrentMap) Touch(key string) bool
- type ConcurrentMapShard
- type Item
- type ItemPoolManager
- type Sizer
Constants ¶
const ( // ShardCount is the number of shards used by the map. ShardCount = 32 // ShardCount32 is the number of shards used by the map pre-casted to uint32 to avoid performance issues. ShardCount32 uint32 = uint32(ShardCount) )
Variables ¶
This section is empty.
Functions ¶
func Hash ¶ added in v0.4.0
Hash returns a 32-bit hash of key derived from xxhash64. Exported so other packages (e.g. the sharded eviction wrapper) can use the same hash as ConcurrentMap and route the same key to the same logical shard — preserving cache-locality when the data shard and eviction shard have different counts.
xxhash is already a direct dependency for cluster/ring.go consistent hashing; consolidating here removes the inlined FNV-1a implementation and gives ~1-3% speedup for keys longer than ~8 bytes plus better avalanche characteristics. Callers should treat the return value as opaque.
We fold the 64-bit xxhash output into 32 bits via XOR of the high and low halves — cheap, preserves all entropy, and matches what Go's standard maphash does when callers want a 32-bit slot index.
Types ¶
type ConcurrentMap ¶
type ConcurrentMap struct {
// contains filtered or unexported fields
}
ConcurrentMap is a "thread" safe map of type string:*cache.Item. To avoid lock bottlenecks this map is divided into several (ShardCount) map shards.
func (*ConcurrentMap) All ¶ added in v0.4.1
func (cm *ConcurrentMap) All() iter.Seq2[string, *Item]
All returns an iter.Seq2 that yields every (key, *Item) pair across all shards. Each shard is walked under its own RLock, released before moving to the next shard — concurrent writers to a different shard are not blocked.
IMPORTANT: the yielded *Item points directly into the live map. Callers MUST treat it as read-only and copy if they need to retain the value past the yield. The shard's RLock is held during yield, so a long-running consumer body will block writers to that shard. Drain into a local slice first if the consumer needs to do I/O or block.
Replaces the previous IterBuffered channel-based iterator: no fan-in goroutines, no per-shard channel allocations.
func (*ConcurrentMap) Count ¶
func (cm *ConcurrentMap) Count() int
Count returns the number of items in the map.
Lock-free: each shard maintains its cardinality as an atomic.Int64 (mutated under the shard lock alongside items). Count() is the sum of the 32 atomics. The previous implementation walked all 32 shard RLocks per call, which serialized with writers and was the dominant cost in the eviction inner loop's `for backend.Count(ctx) > backend.Capacity()`.
func (*ConcurrentMap) Get ¶
func (cm *ConcurrentMap) Get(key string) (*Item, bool)
Get retrieves an element from map under given key.
func (*ConcurrentMap) GetCopy ¶ added in v0.2.2
func (cm *ConcurrentMap) GetCopy(key string) (*Item, bool)
GetCopy retrieves a copy of the item under the given key.
func (*ConcurrentMap) GetShard ¶
func (cm *ConcurrentMap) GetShard(key string) *ConcurrentMapShard
GetShard returns shard under given key.
func (*ConcurrentMap) Has ¶
func (cm *ConcurrentMap) Has(key string) bool
Has checks if key is present in the map.
func (*ConcurrentMap) Pop ¶
func (cm *ConcurrentMap) Pop(key string) (*Item, bool)
Pop removes an element from the map and returns it.
func (*ConcurrentMap) Remove ¶
func (cm *ConcurrentMap) Remove(key string)
Remove removes the value under the specified key.
func (*ConcurrentMap) Set ¶
func (cm *ConcurrentMap) Set(key string, value *Item)
Set sets the given value under the specified key.
func (*ConcurrentMap) Touch ¶ added in v0.2.2
func (cm *ConcurrentMap) Touch(key string) bool
Touch updates the last access time and access count for a key.
type ConcurrentMapShard ¶
ConcurrentMapShard is a "thread" safe string to `*cache.Item` map shard.
count tracks len(items) under the same lock as items, but as an atomic so Count() (sum of 32 shard counts) can read it without acquiring any locks. This eliminates the lock-storm in the eviction inner loop's per-iteration Count() check.
type Item ¶ added in v0.1.8
type Item struct {
Key string // key of the item
Value any // value of the item
LastAccess time.Time // last access time
LastUpdated time.Time // last write/version assignment time (distributed usage)
Size int64 // size in bytes
Expiration time.Duration // expiration duration
AccessCount uint32 // number of times the item has been accessed
Version uint64 // logical version (monotonic per key)
Origin string // originating node id (tiebreaker)
}
Item is a struct that represents an item in the cache (v2 optimized layout). It mirrors pkg/cache.Item behavior but with minor layout tweaks for locality.
func (*Item) SetSize ¶ added in v0.1.8
SetSize computes and sets Size using fast paths and pooled encoder/buffer. This preserves original behavior (size of serialized value) but reduces allocations.
type ItemPoolManager ¶ added in v0.1.8
type ItemPoolManager struct {
// contains filtered or unexported fields
}
ItemPoolManager manages Item object pools for memory efficiency (v2).
func NewItemPoolManager ¶ added in v0.1.8
func NewItemPoolManager() *ItemPoolManager
NewItemPoolManager creates a new ItemPoolManager with default configuration (v2).
func (*ItemPoolManager) Get ¶ added in v0.1.8
func (m *ItemPoolManager) Get() *Item
Get retrieves an Item from the pool (v2).
func (*ItemPoolManager) Put ¶ added in v0.1.8
func (m *ItemPoolManager) Put(it *Item)
Put returns an Item to the pool (v2).