The Valid-Checking LRU (Least Recently Used) cache is a set-associative cache implementation that pre-allocates all cache blocks at initialization. Unlike dynamically allocated caches, this approach marks blocks as valid=false when they are not in use.
Upon accessing a block:
If the block exists in the cache (Hit), it is moved to the front of the list.
If it does not exist (Miss), an invalid block is reused if available.
If all blocks are valid=true, the least recently used (LRU) block is evicted. Then, the new block is created and moved to the front of the list.
Empty but Preallocated Blocks.
Unlike Dynamic-Way LRU, all blocks are initialized with valid=false at the start.
Miss! But there are still invalid blocks available.
Instead of evicting, use an invalid block.
Mark it valid=true and move it to the front.
Miss! But still, there are invalid blocks available.
Use an invalid block, mark it valid, move it to the front.
Hit! A1115550 is already in the set.
Move it to the front (most recently used).
After accessing A1115552 and A1115553, the set is full.
Every block is now valid=true, so next miss must trigger an eviction.
Miss! No invalid blocks remain.
Evict LRU block (A1115551, closest to Dummy Tail).
Replace it with A1115560 and move to the front.
Hit!
A1115550 is in the set.
Move it to the front (MRU).
O(1)
.Two scenarios for handling a miss:
Case 1: Use an invalid block Search for a valid=false block: O(N) (N = set_degree, worst case is that all blocks are valid). Update block’s tag and set valid=true: O(1). Move block to head (most recently used): O(1).
Overall: O(N) + O(1) + O(1) = O(N)
(Worst case: scanning all blocks in the set to find an invalid one.)
Case 2: Evict LRU block (All blocks are valid=true) Find LRU block (always at the tail): O(1). Replace with new block, update tag, set valid=true: O(1). Move to head (most recently used): O(1).
Overall: O(1) + O(1) + O(1) = O(1)
Find in HashMap: O(1).
Remove from current position: O(1).
Insert at the front: O(1).
Overall: O(1) + O(1) + O(1) = O(1)
.
Identify LRU block (always at the tail): O(1).
Remove from doubly linked list: O(1).
Remove from HashMap: O(1).
Insert new block at head: O(1).
Overall: O(1) + O(1) + O(1) + O(1) = O(1)
.
Operation | Complexity |
---|---|
Lookup | O(1) |
Insert | O(N) |
Move to Head | O(1) |
Eviction | O(1) |
Overall Complexity: O(N)
.
cargo
Clone the repository
git clone https://github.com/mellivorandy/cache-miss-analyzer.git
From the project root, run:
cargo build
To execute the program with custom arguments, use the following command:
cargo run -p valid_checking_lru -- <trace_file_name> <cache_size> <block_size> <set_degree>
In this project structure, the trace.txt file is located in cache-miss-analyzer/data, change the path if the trace file is moved or new trace files are added.
Note: If the file path remains unchanged, use the path as given. Simply copy and paste the following command into your terminal:
cargo run -p valid_checking_lru -- ./data/trace.txt 128 4 1
A [cfg(test)]
test module is included, referencing a trace.txt file for unit tests. To run them:
cargo test -p valid_checking_lru -- --nocapture
This prints the non-empty sets.
I sincerely appreciate the incredible work behind Mermaid.js, an open-source diagramming tool that makes visualizing complex ideas effortless. Huge thanks to the developers and contributors who maintain and improve this fantastic project!