Cache explorer: what stays and what goes
A cache is small. When it is full, it must remove something. It must also decide when a saved value is too old. Change the size, the removal rule and the expiry time, and see what the app fetches again.
The idea
Every cache answers two questions. The first is: is this value still fresh? An expiry time (a TTL) answers that. The second is: what do we remove when the cache is full? An eviction rule answers that.
The two questions are separate. A short expiry does not help when the cache is full of the wrong things. A good removal rule does not help when the saved price is wrong. This tool lets you change one rule at a time. The caching and eviction guide explains the ideas in words.
Try it
Result
Request by request
The same situation with each removal rule
This table uses your cache size and your expiry time. The row for your current rule is marked.
| Removal rule | Hits | Fetched | Removed to make room |
|---|
What this shows
Pick a situation to see what it shows.
Without JavaScript
The controls above need JavaScript. If it is off, use these tables. They show the start values of each situation, with every removal rule. With JavaScript on, you can change the size and the expiry time as well.
| Situation and rule | Hits | Fetched | Removed to make room | Other |
|---|---|---|---|---|
| Same avatar on every row Least recently used (LRU), 250 KB cache | 6 of 13 | 650 KB | 4 | - |
| Same avatar on every row Oldest first (FIFO), 250 KB cache | 4 of 13 | 750 KB | 6 | - |
| Same avatar on every row Largest first (size-based), 250 KB cache | 6 of 13 | 650 KB | 4 | - |
| Same avatar on every row Lowest priority first, 250 KB cache | 6 of 13 | 650 KB | 4 | - |
| One big file arrives Least recently used (LRU), 500 KB cache | 0 of 13 | 950 KB | 7 | - |
| One big file arrives Oldest first (FIFO), 500 KB cache | 0 of 13 | 950 KB | 7 | - |
| One big file arrives Largest first (size-based), 500 KB cache | 3 of 13 | 800 KB | 4 | - |
| One big file arrives Lowest priority first, 500 KB cache | 0 of 13 | 950 KB | 7 | - |
| A price that changes Least recently used (LRU), 100 KB cache | 5 of 6 | 5 KB | 0 | 4 |
| A price that changes Oldest first (FIFO), 100 KB cache | 5 of 6 | 5 KB | 0 | 4 |
| A price that changes Largest first (size-based), 100 KB cache | 5 of 6 | 5 KB | 0 | 4 |
| A price that changes Lowest priority first, 100 KB cache | 5 of 6 | 5 KB | 0 | 4 |
| Offline timetable Least recently used (LRU), 500 KB cache | 0 of 10 | 1200 KB | 6 | 1 miss |
| Offline timetable Oldest first (FIFO), 500 KB cache | 0 of 10 | 1200 KB | 6 | 1 miss |
| Offline timetable Largest first (size-based), 500 KB cache | 0 of 10 | 1200 KB | 6 | 1 miss |
| Offline timetable Lowest priority first, 500 KB cache | 1 of 10 | 1000 KB | 5 | 0 misses |
The last column shows old values shown for the price situation, and misses of must-have data for the timetable situation.
The price situation, with a least-recently-used cache and different expiry times:
| Expiry time | Hits | Fetched | Old values shown |
|---|---|---|---|
| No expiry | 5 of 6 | 5 KB | 4 |
| 10 seconds | 0 of 6 | 30 KB | 0 |
| 30 seconds | 3 of 6 | 15 KB | 0 |
| 60 seconds | 4 of 6 | 10 KB | 3 |
How the model works
This is a small model, not a real app. These are my choices:
- Sizes are in KB. The cache holds a fixed number of KB. A real cache may count items instead, or use memory cost. See the guide.
- When a new item does not fit, the rule removes items one at a time until it fits. An item that is bigger than the whole cache is fetched but not saved.
- Rules: least recently used removes the item that was used longest ago. Oldest first removes the item that was saved first, whatever its use. Largest first removes the biggest item. Lowest priority first removes items with the lowest priority number. When two items tie, the one used longest ago goes first. Because of this, "largest first" and "lowest priority" give the same result as LRU when sizes or priorities are all equal. Only the timetable situation uses different priorities.
- The expiry time counts from the moment the item was fetched, not from the last use. An expired item is fetched again in full.
- The server changes the price at 25 s and 65 s. The model knows this. A real app does not, and that is why it needs an expiry time or a check with the server.
- The model leaves out: checking with the server before fetching again (an ETag check costs a small request, not a full fetch), memory warnings from the system, and files that are written while another request runs.
- The model uses no random numbers, so the same settings give the same result every time. Nothing is saved and nothing leaves your browser.