8.4 Least Recently Used (LRU) Page Replacement & Stack Algorithms
π‘ Core Intuitionβ
π³ The Everyday Analogy: The Cook's Countertopβ
Imagine a master chef preparing a complex banquet in a compact restaurant kitchen:
The Chef's Countertop Eviction Pipeline
Contrasting arrival-based clearing with recency-of-use retention
Three-Item Cutting Board
The cutting board can fit only three active ingredient containers simultaneously.
Fresh Rosemary Arrives
A recipe requires fresh rosemary, but the cutting board is completely packed.
Evicting the Idle Jar
Salt was used 10 seconds ago; garlic 30 seconds ago; olive oil has sat untouched for 20 minutes.
- Least Recently Used (LRU): The premier practical approximation of the Optimal algorithm. It assumes the recent past is the best predictor of the immediate future (Temporal Locality).
- The Stack Property: LRU is a certified Stack Algorithm, meaning its memory state with frames is always a subset of frames, rendering it mathematically immune to Belady's Anomaly.
π» Bridging to Computer Scienceβ
While the Optimal algorithm looks forward into the future (which is impossible in an online operating system), the Least Recently Used (LRU) algorithm looks backward into the recent past:
Because program execution exhibits strong Temporal Locality of Reference, a page that has not been referenced for a substantial interval is statistically least likely to be referenced in the immediate future.
π Core Deep-Dive & Conceptsβ
1. The LRU Algorithm Mechanicsβ
Eviction Ruleβ
When a page fault occurs and no physical frame is empty:
- For each page resident in physical RAM, examine its most recent time of reference.
- Select as victim the page that has remained unreferenced for the longest duration (the oldest timestamp in the past).
- Evict the victim page, load the incoming page, and tag it with the current timestamp.
2. Comprehensive 20-Reference Traceβ
Let us trace the identical 20-reference string evaluated under FIFO (15 faults) and OPT (9 faults), using allocated physical frames:
| Step | Page Ref | Frame 1 | Frame 2 | Frame 3 | Event | Backward History of Resident Pages | Victim Selected |
|---|---|---|---|---|---|---|---|
| 1 | 7 | 7 | β | β | Fault | β | None (Cold) |
| 2 | 0 | 7 | 0 | β | Fault | β | None (Cold) |
| 3 | 1 | 7 | 0 | 1 | Fault | β | None (Cold) |
| 4 | 2 | 2 | 0 | 1 | Fault | 1 (step 3), 0 (step 2), 7 (step 1) | 7 (Least Recently Used) |
| 5 | 0 | 2 | 0 | 1 | Hit | Recency order: 0 (newest), 2, 1 | None |
| 6 | 3 | 2 | 0 | 3 | Fault | 0 (step 5), 2 (step 4), 1 (step 3) | 1 (Least Recently Used) |
| 7 | 0 | 2 | 0 | 3 | Hit | Recency order: 0, 3, 2 | None |
| 8 | 4 | 4 | 0 | 3 | Fault | 0 (step 7), 3 (step 6), 2 (step 4) | 2 (Least Recently Used) |
| 9 | 2 | 4 | 0 | 2 | Fault | 4 (step 8), 0 (step 7), 3 (step 6) | 3 (Least Recently Used) |
| 10 | 3 | 4 | 3 | 2 | Fault | 2 (step 9), 4 (step 8), 0 (step 7) | 0 (Least Recently Used) |
| 11 | 0 | 0 | 3 | 2 | Fault | 3 (step 10), 2 (step 9), 4 (step 8) | 4 (Least Recently Used) |
| 12 | 3 | 0 | 3 | 2 | Hit | Recency order: 3, 0, 2 | None |
| 13 | 2 | 0 | 3 | 2 | Hit | Recency order: 2, 3, 0 | None |
| 14 | 1 | 0 | 1 | 2 | Fault | 2 (step 13), 3 (step 12), 0 (step 11) | 0 (Wait: 2 at 13, 3 at 12, 0 at 11 0 is oldest, but 3 was older than 1? Let's check: 0 is at 11, 3 is at 12, 2 is at 13 0 replaced by 1!) |
| 15 | 2 | 1 | 3 | 2 | Hit | Recency order: 2, 1, 3 | None |
| 16 | 0 | 1 | 0 | 2 | Fault | 2 (step 15), 1 (step 14), 3 (step 12) | 3 (Least Recently Used) |
| 17 | 1 | 1 | 0 | 2 | Hit | Recency order: 1, 0, 2 | None |
| 18 | 7 | 1 | 0 | 7 | Fault | 1 (step 17), 0 (step 16), 2 (step 15) | 2 (Least Recently Used) |
| 19 | 0 | 1 | 0 | 7 | Hit | Recency order: 0, 7, 1 | None |
| 20 | 1 | 1 | 0 | 7 | Hit | Recency order: 1, 0, 7 | None |
Performance Summary for 3 Frames:β
- Total References:
- Total Page Faults:
- Total Page Hits:
- Hit Ratio:
Master Multi-Algorithm Comparison:β
- FIFO: Page Faults ( hit rate)
- LRU: Page Faults ( hit rate)
- OPT (Theoretical Lower Bound): Page Faults ( hit rate)
3. Implementation Schemes for Pure LRUβ
Implementing pure LRU in hardware or software requires tracking recency on every single memory reference:
Why Pure LRU is Impractical in Hardwareβ
- In modern processors executing instructions per second, updating a 64-bit timestamp register or rewriting 6 pointers in a doubly-linked list on every single instruction fetch causes intolerable hardware power and latency overhead.
- Consequently, commercial operating systems use LRU Approximations (such as the Second-Chance / Clock algorithm discussed in Topic 8.2).
4. Mathematical Proof: The Stack Property & Immunity to Belady's Anomalyβ
LRU belongs to the elite family of Stack Algorithms.
Formal Definitionβ
Let denote the set of pages resident in physical memory with frames at discrete time step . An algorithm satisfies the Stack Property if and only if:
Proof Sketch for LRUβ
- Under LRU, at any time , the pages resident in memory are precisely the most recently referenced unique pages from the reference history .
- In an -frame system, the resident pages are the most recently referenced unique pages.
- Clearly, the set of the top most recently referenced pages is a strict subset of the top most recently referenced pages:
- Therefore, if a page reference hits in an -frame system (), it is guaranteed to hit in the -frame system ().
- A hit can never turn into a fault when frames are added!
- Conclusion: LRU is provably immune to Belady's Anomaly.
5. Counting-Based Page Replacement Algorithmsβ
Operating systems researchers also explored frequency-counting heuristics:
π In The Real World: Production Case Studyβ
High-Performance In-Memory Caching: Redis & Caffeineβ
While pure LRU is too expensive for hardware MMUs, it is the industry standard for application-layer memory caches (Redis, Memcached, Java Caffeine):
Redis Cache Eviction Strategies
Production memory reclaim algorithms configured via maxmemory-policy
allkeys-lru
Global LRU- Evicts the least recently used keys among all stored keys in the dataset.
- Optimal default strategy when traffic exhibits power-law or zipfian access patterns.
volatile-lru
TTL-Scoped LRU- Restricts LRU eviction strictly to keys configured with an explicit expiration TTL.
- Guarantees permanent non-expiring configuration keys remain untouched in memory.
allkeys-lfu
Frequency Counter- Evicts keys using logarithmic 8-bit frequency access counters with decay time.
- Protects frequently read hot keys from being displaced by bursty temporary scans.
- Approximated LRU in Redis:
- Rather than maintaining an exact linked list across keys (which wastes gigabytes in pointer overhead), Redis samples 5 random keys and evicts the one with the oldest idle timestamp.
- This 5-sample approximation delivers of the hit-rate of pure LRU with zero extra memory overhead!
- Window TinyLFU (W-TinyLFU):
- Modern systems (Caffeine cache, Cassandra) combine LRU and LFU: an admission window uses LRU to capture bursty temporal spikes, and a main space uses a Count-Min Sketch (LFU) to protect frequently accessed long-term items.
π― Exam & Interview Pitfall Checkβ
Question 1: Why is LRU classified as a Stack Algorithm, whereas FIFO is not? Answer:
- In LRU, the set of pages resident in memory of size is always a subset of the pages resident in memory of size for every reference step (). Adding an extra frame simply extends the bottom of the recency stack by one entry without altering the order of the top pages.
- In FIFO, adding an extra frame alters the relative arrival eviction order of pages across subsequent steps. A page that would have been preserved in a smaller frame set might get evicted in a larger frame set, causing .
- Because LRU satisfies the inclusion stack property, it is mathematically immune to Belady's Anomaly.
Question 2: Trace the LRU page replacement algorithm for the reference string: with frames. Find the total number of page faults and page hits. Answer:
- Ref
2: Fault[2, β, β] - Ref
3: Fault[2, 3, β] - Ref
2: Hit[3, 2, β](Recency: 2 newest) - Ref
1: Fault[3, 2, 1] - Ref
5: Fault. Resident:3, 2, 1. Past order: 1 (at 4), 2 (at 3), 3 (at 2).- Evict
3! Frames:[2, 1, 5].
- Evict
- Ref
2: Hit. Recency:1, 5, 2. - Ref
4: Fault. Resident:2, 1, 5. Past order: 2 (at 6), 5 (at 5), 1 (at 4).- Evict
1! Frames:[5, 2, 4].
- Evict
- Ref
5: Hit. Recency:2, 4, 5. - Ref
3: Fault. Resident:5, 2, 4. Past order: 5 (at 8), 4 (at 7), 2 (at 6).- Evict
2! Frames:[4, 5, 3].
- Evict
- Ref
2: Fault. Resident:4, 5, 3. Past order: 3 (at 9), 5 (at 8), 4 (at 7).- Evict
4! Frames:[5, 3, 2].
- Evict
- Ref
5: Hit. Recency:3, 2, 5. - Ref
2: Hit. Recency:3, 5, 2.
- Total Page Faults:
- Total Page Hits:
- Hit Ratio:
- Forgetting to Update Recency on a HIT: In LRU, when a page reference results in a Hit, you MUST update its timestamp / move it to the top of the recency stack! Leaving its timestamp unchanged treats it as cold, causing you to evict a hot page erroneously.
- The "LRU is Implemented via Simple Linked List" Myth: In hardware, an MMU cannot traverse a software linked list on every instruction. Hardware approximations like the Clock Algorithm using a single Reference Bit are what real operating systems execute.