Mean miss ratio
Five datasets, lower is better.
Simple and Scalable caching with three Static FIFO queues
Most objects in a cache are never requested again. S3-FIFO lets them go soon after they arrive, so the space goes to objects that are reused, and a hit only bumps a two-bit counter, with no lock.
S3-FIFO runs in
How it works
New objects wait in a small queue. Most are never requested again and leave quickly. Objects that are reused move on to the main queue, which keeps them for as long as they keep getting hits.
S holds about 10% of the cache. An object hit twice while in S moves to M; the rest are evicted as soon as S needs room. This is quick demotion.
G keeps only the keys of objects evicted from S, as many as M holds. A key requested again while it is in G goes straight into M.
When M needs room, it checks its oldest object: with a counter above zero, it is reinserted with the counter lowered by one (lazy promotion); otherwise it is evicted.
A hit increments a counter capped at 3 with one atomic update. Nothing moves and nothing locks on the hot path, so S3-FIFO scales with threads.
Results
We compared S3-FIFO with 12 state-of-the-art algorithms on 6,594 traces from 14 datasets. It has lower miss ratios overall, and the lowest mean miss ratio on 10 of the 14 datasets.
Five datasets, lower is better.
Up to 46% less cache
For the same 10% miss ratio.
Scales with threads
A hit never takes a lock, so more threads give more throughput.
Why it works
Cache workloads are skewed, and a cache only ever sees a short stretch of requests. In that stretch, most objects are requested once: with a cache at 10% of a trace’s footprint, about 72% of objects are not reused before they are evicted.
LRU keeps each of these one-hit wonders for a full trip through the queue. S3-FIFO’s small queue lets them go after a short stay, which leaves the main queue to the objects that earn their place.
Share of evicted objects, by cache size as a fraction of the objects in the trace.
Use it
Experiment with the Python package, pick a production library in your language, or replay your own traces in libCacheSim.
pip install cachemonCache from cachemonCache import S3FIFO
# A cache that holds up to 1,000 objects
cache = S3FIFO(cache_size=1000)
# Add an object; it expires after 60 seconds
cache.put("key", "value", ttl_sec=60)
# Look it up
print(cache.get("key")) # value
print("key" in cache) # True
# Remove it
cache.delete("key")
print(cache.get("key")) # None
# It also behaves like a dict
cache["answer"] = 42
print(cache["answer"]) # 42 Adoption
S3-FIFO and close variants of it run in proxies, databases, storage engines and stream processors. Each entry links to the code, pull request or docs that show it.
Its README names S3-FIFO; its docs call it a Clock-PRO variant “very similar to” S3-FIFO.
Open pull requests and proposals.
Carnegie Mellon University, Parallel Data Laboratory, Emory University, SimBioSys Lab, Meta, Google Cloud, AWS, Microsoft Azure, CloudLab, the Sloan Foundation, VMware and NSF.
Twitter, Meta, Tencent, Microsoft, Wikimedia and CloudPhysics.
We would love to list you, and to hear how it went.
More from cacheMon: SIEVE · libCacheSim · cachemon.org