Answers · The systems around the model
Why can a higher hit rate still mean the cache is making things slower?
In shortHit rate counts hits equally and ignores what each hit costs, so a cache with many cheap hits can save less than one with few expensive hits, and can even add more work than it removes.
A higher hit rate can make things slower because the hit rate counts events, not work saved. It gives a hit on a two-second answer the same weight as a hit on a tenth-of-a-millisecond answer, and it says nothing about the cost the cache adds to every read.
- work avoided per second
- read rate
- hit rate
- cost of producing one answer when it is not held
- hits per second, which is what a hit rate alone gives you
The product is the first correction. At 1000 reads per second, a cache with and s avoids seconds of work per second. A cache with and ms avoids seconds per second. The second answers more than twice the share of reads and saves roughly one nine-hundredth of the work.
There is a second factor the hit rate omits, and it is the one that lets a cache be a net loss. Let be the cost of consulting the cache on every read, hit or miss: the lookup, the network hop, the deserialisation. A hit pays . A miss pays .
The average read costs with the cache and without it. Subtracting gives per read. So the cache helps only when exceeds , and the size of alone cannot settle it. Suppose ms and ms. A hit costs 12 ms, a miss costs 22 ms, and at the average read costs ms. Going straight to the store costs 10 ms. The cache is 3 ms slower per read at a 90 per cent hit rate. At 500 reads per second that is ms, or 1.5 seconds of extra work every second.
The natural guess is that 90 per cent must beat 40 per cent because it is a bigger share. A hit rate is a ratio of counts, and it cancels the size of the thing being counted. It cannot tell you whether the hits are on answers that cost two seconds or on answers that cost a tenth of a millisecond, and it cannot tell you whether serving a hit through the cache costs more than serving the read without it. The scoreboard has no column for either.
The practical measurement is therefore per kind of answer: how many reads, how many hits, what a miss costs, and what the cache adds. Multiply and subtract. A cache whose hits are all on expensive answers can be valuable at a hit rate people would call broken, and a cache whose hits are all on cheap answers can be a net loss while its dashboard looks healthy. The hit rate is not wrong; it is one factor out of three, and the missing factor is the one that varies most.
The tail is made of misses
There is a second way a high hit rate misleads. A hit is fast because it is a hit, so it cannot be in the slowest requests. Every request in the tail went to the store. Moving from 80 to 95 per cent can leave the 99th percentile unchanged, because the remaining 5 per cent are the only requests that were ever slow. Raising the hit rate changes how many reads are slow. Improving the miss path changes how slow a miss is. Those are different projects.
When the ordering is safe
If every miss costs the same and the lookup overhead is negligible, then is ordered by , and a higher hit rate does mean more work saved. The ordering also holds if you compare caches on the same mix of answers and the same , because is then a common factor. It fails when the mix changes, when the cache is consulted on every read, or when the hit rate rises by keeping cheap answers and evicting expensive ones. Then the high hit rate can be a record of many small savings and one large loss.
Worth keeping
- A cache is worth having only when the share of reads it answers multiplied by the cost of a miss exceeds the cost of consulting it on every read.
- The slowest requests are all misses, so improving the tail is work on the miss path, not on the hit rate.
- Replaying a recorded hour at several cache sizes answers whether more memory would help without deploying anything.
Where this goes next
This question is one step of Keeping the Answer Nearby, a course that works through its subject from the beginning. The page that teaches this part of it is Knowing Whether It Is Working, and it reads the whole way through whether or not you have an account.
What an account changes is the practice: problems standing under every idea, marked with a reason rather than a tick, in a copy of the course that is yours.
Read that pageThe whole courseOther questions people ask about this
- What's the difference between a CDN cache and caching inside my own app?A CDN cache sits near the user and can only hold answers that are identical for everyone, while a cache inside your app can be personal but exists once per process.
- What's the difference between LRU and LFU, and which one should I use?LRU drops the item unused for longest; LFU drops the item requested least often. Both guess at future use, and the cheap win is refusing one-off arrivals rather than counting requests.
- Should the cache go in front of my app or between the app and the database?Put the shared cache between the app and the database by default, and push a copy in front of the app only for the part of a response that every reader gets identically.
- Why can't a system just stay consistent and available when the network splits?During a split, a cut-off machine can only answer from the data it already holds, so it must either risk being wrong or refuse to answer.
- How can I tell if my traffic is bursty or just high volume?Compare the variance of the gaps between arrivals with the square of their average gap: high volume alone does not make traffic bursty.
- Why does average latency hide the slow requests users actually feel?Waiting times are lopsided, so the average sits between the common case and the bad case and describes neither, and it is the bad case that users keep meeting.