@@ -8,12 +8,12 @@ import (
88 "time"
99)
1010
11- const numShards = 4
11+ const numShards = 16
1212
1313// s3fifo implements the S3-FIFO eviction algorithm from SOSP'23 paper
1414// "FIFO queues are all you need for cache eviction"
1515//
16- // This implementation uses 4 -way sharding for improved concurrent performance.
16+ // This implementation uses 16 -way sharding for improved concurrent performance.
1717// Each shard is an independent S3-FIFO instance with its own queues and lock.
1818//
1919// Algorithm per shard:
@@ -63,7 +63,7 @@ type entry[K comparable, V any] struct {
6363// newS3FIFO creates a new sharded S3-FIFO cache with the given total capacity.
6464func newS3FIFO [K comparable , V any ](capacity int ) * s3fifo [K , V ] {
6565 if capacity <= 0 {
66- capacity = 10000
66+ capacity = 16384 // 2^14, divides evenly by 16 shards
6767 }
6868
6969 // Divide capacity across shards (round up to avoid zero-capacity shards)
@@ -102,20 +102,10 @@ func newShard[K comparable, V any](capacity int) *shard[K, V] {
102102 }
103103}
104104
105- // getShard returns the shard for a given key using maphash .
105+ // getShard returns the shard for a given key using type-optimized hashing .
106106func (c * s3fifo [K , V ]) getShard (key K ) * shard [K , V ] {
107- var h maphash.Hash
108- h .SetSeed (c .seed )
109- //nolint:errcheck,gosec // maphash.Hash.WriteString never returns error
110- h .WriteString (any (key ).(string ))
111- return c .shards [h .Sum64 ()% numShards ]
112- }
113-
114- // getShardInt is an optimized path for common key types.
115- func (c * s3fifo [K , V ]) getShardInt (key K ) * shard [K , V ] {
116107 switch k := any (key ).(type ) {
117108 case int :
118- // Safe: modulo result is always in [0, numShards)
119109 if k < 0 {
120110 k = - k
121111 }
@@ -136,14 +126,19 @@ func (c *s3fifo[K, V]) getShardInt(key K) *shard[K, V] {
136126 h .WriteString (k )
137127 return c .shards [h .Sum64 ()% numShards ]
138128 default :
139- return c .getShard (key )
129+ // Fallback for other types: convert to string and hash
130+ var h maphash.Hash
131+ h .SetSeed (c .seed )
132+ //nolint:errcheck,gosec // maphash.Hash.WriteString never returns error
133+ h .WriteString (any (key ).(string ))
134+ return c .shards [h .Sum64 ()% numShards ]
140135 }
141136}
142137
143138// getFromMemory retrieves a value from the in-memory cache.
144139// On hit, increments frequency counter (used during eviction).
145140func (c * s3fifo [K , V ]) getFromMemory (key K ) (V , bool ) {
146- return c .getShardInt (key ).get (key )
141+ return c .getShard (key ).get (key )
147142}
148143
149144func (s * shard [K , V ]) get (key K ) (V , bool ) {
@@ -176,7 +171,7 @@ func (s *shard[K, V]) get(key K) (V, bool) {
176171
177172// setToMemory adds or updates a value in the in-memory cache.
178173func (c * s3fifo [K , V ]) setToMemory (key K , value V , expiry time.Time ) {
179- c .getShardInt (key ).set (key , value , expiry )
174+ c .getShard (key ).set (key , value , expiry )
180175}
181176
182177func (s * shard [K , V ]) set (key K , value V , expiry time.Time ) {
@@ -224,7 +219,7 @@ func (s *shard[K, V]) set(key K, value V, expiry time.Time) {
224219
225220// deleteFromMemory removes a value from the in-memory cache.
226221func (c * s3fifo [K , V ]) deleteFromMemory (key K ) {
227- c .getShardInt (key ).delete (key )
222+ c .getShard (key ).delete (key )
228223}
229224
230225func (s * shard [K , V ]) delete (key K ) {
@@ -404,7 +399,7 @@ func (c *s3fifo[K, V]) queueLens() (small, main int) {
404399
405400// isInSmall returns whether a key is in the small queue (for testing).
406401func (c * s3fifo [K , V ]) isInSmall (key K ) bool {
407- s := c .getShardInt (key )
402+ s := c .getShard (key )
408403 s .mu .RLock ()
409404 defer s .mu .RUnlock ()
410405 if ent , ok := s .items [key ]; ok {
@@ -415,7 +410,7 @@ func (c *s3fifo[K, V]) isInSmall(key K) bool {
415410
416411// setExpiry sets the expiry time for a key (for testing).
417412func (c * s3fifo [K , V ]) setExpiry (key K , expiry time.Time ) {
418- s := c .getShardInt (key )
413+ s := c .getShard (key )
419414 s .mu .Lock ()
420415 defer s .mu .Unlock ()
421416 if ent , ok := s .items [key ]; ok {
0 commit comments