Basis Lab

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.

FIG 1What the hit rate leaves out
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 hit rate supplies two of these three factors. The missing one varies by orders of magnitude between kinds of answer.

The product is the first correction. At 1000 reads per second, a cache with p=0.40p = 0.40 and c=2c = 2 s avoids 1000×0.40×2=8001000 \times 0.40 \times 2 = 800 seconds of work per second. A cache with p=0.90p = 0.90 and c=1c = 1 ms avoids 1000×0.90×0.001=0.91000 \times 0.90 \times 0.001 = 0.9 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 hh be the cost of consulting the cache on every read, hit or miss: the lookup, the network hop, the deserialisation. A hit pays hh. A miss pays h+ch + c.

Wnet=r(pc−h)W_{net} = r(p c - h)

The average read costs ph+(1−p)(h+c)p h + (1-p)(h+c) with the cache and cc without it. Subtracting gives pc−hp c - h per read. So the cache helps only when pcp c exceeds hh, and the size of pp alone cannot settle it. Suppose c=10c = 10 ms and h=12h = 12 ms. A hit costs 12 ms, a miss costs 22 ms, and at p=0.90p = 0.90 the average read costs 0.90×12+0.10×22=10.8+2.2=130.90 \times 12 + 0.10 \times 22 = 10.8 + 2.2 = 13 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 500×3=1500500 \times 3 = 1500 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 cc and the lookup overhead hh is negligible, then pc−hp c - h is ordered by pp, 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 hh, because cc 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 course

Other questions people ask about this

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

Read alongside