-
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcache_composition.go
More file actions
124 lines (113 loc) Β· 6.17 KB
/
cache_composition.go
File metadata and controls
124 lines (113 loc) Β· 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package hot
import (
"github.com/samber/hot/pkg/arc"
"github.com/samber/hot/pkg/base"
"github.com/samber/hot/pkg/fifo"
"github.com/samber/hot/pkg/lfu"
"github.com/samber/hot/pkg/lru"
"github.com/samber/hot/pkg/metrics"
"github.com/samber/hot/pkg/safe"
"github.com/samber/hot/pkg/sharded"
"github.com/samber/hot/pkg/sieve"
"github.com/samber/hot/pkg/tinylfu"
"github.com/samber/hot/pkg/twoqueue"
"github.com/samber/hot/pkg/wtinylfu"
)
//
// This diagram shows an example of a composition of the HotCache[K, V] and its layers.
// Combining multiple encapsulation has a small cost (~1ns per call), but offers great customization.
//
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β hot.HotCache[K, V] β
// β (High-level, feature-complete) β
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β
// βΌ
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β pkg/sharded.ShardedInMemoryCache β
// β (Sharding layer) β
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β β β β β
// βΌ βΌ βΌ βΌ βΌ
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β pkg/metrics.InstrumentedCache[K, V] β
// β (Metric collection layer) β
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β
// βΌ
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β pkg/safe.SafeInMemoryCache[K, V] β
// β (Thread safety layer) β
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β
// βΌ
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β pkg/lru.LRUCache[K, V] β
// β pkg/lfu.LFUCache[K, V] β
// β pkg/arc.ARCCache[K, V] β
// β pkg/fifo.FIFOCache[K, V] β
// β pkg/twoqueue.TwoQueueCache[K, V] β
// β pkg/sieve.SIEVECache[K, V] β
// β (Eviction policies) β
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
//
// composeInternalCache creates an internal cache instance based on the provided configuration.
// It handles sharding, locking, and different eviction algorithms.
func composeInternalCache[K comparable, V any](
locking bool,
algorithm EvictionAlgorithm,
capacity int,
shards uint64,
shardIndex int,
shardingFn sharded.Hasher[K],
onEviction base.EvictionCallback[K, V],
collectorBuilder func(shard int) metrics.Collector,
) base.InMemoryCache[K, *item[V]] {
assertValue(capacity >= 0, "capacity must be a positive value")
assertValue((shards > 1 && shardingFn != nil) || shards <= 1, "sharded cache requires sharding function")
if shards > 1 {
return sharded.NewShardedInMemoryCache(
shards,
func(shardIndex int) base.InMemoryCache[K, *item[V]] {
return composeInternalCache(false, algorithm, capacity, 0, shardIndex, nil, onEviction, collectorBuilder)
},
shardingFn,
)
}
var cache base.InMemoryCache[K, *item[V]]
var onItemEviction base.EvictionCallback[K, *item[V]]
if onEviction != nil {
onItemEviction = func(reason base.EvictionReason, key K, value *item[V]) {
onEviction(reason, key, value.value)
}
}
switch algorithm {
case LRU:
cache = lru.NewLRUCacheWithEvictionCallback(capacity, onItemEviction)
case LFU:
cache = lfu.NewLFUCacheWithEvictionCallback(capacity, onItemEviction)
case TinyLFU:
cache = tinylfu.NewTinyLFUCacheWithEvictionCallback(capacity, onItemEviction)
case WTinyLFU:
cache = wtinylfu.NewWTinyLFUCacheWithEvictionCallback(capacity, onItemEviction)
case TwoQueue:
cache = twoqueue.New2QCacheWithEvictionCallback(capacity, onItemEviction)
case ARC:
cache = arc.NewARCCacheWithEvictionCallback(capacity, onItemEviction)
case FIFO:
cache = fifo.NewFIFOCacheWithEvictionCallback(capacity, onItemEviction)
case SIEVE:
cache = sieve.NewSIEVECacheWithEvictionCallback(capacity, onItemEviction)
default:
panic("unknown cache algorithm")
}
// Using mutexMock costs ~3ns per operation, which is more than the cost of calling base.SafeInMemoryCache abstraction (1ns).
// Using mutexMock is more performant for this library when locking is enabled most of the time.
if locking {
cache = safe.NewSafeInMemoryCache(cache)
}
if collectorBuilder != nil {
cache = metrics.NewInstrumentedCache(cache, collectorBuilder(shardIndex))
}
return cache
}