Skip to content

Commit 0cac4e3

Browse files
committed
Add CAR (Clock with Adaptive Replacement) policy documentation and implementation
- Introduced the CAR policy, combining ARC-like adaptivity with Clock mechanics to enhance concurrency and reduce overhead. - Added detailed documentation outlining the architecture, key operations, performance trade-offs, and example usage. - Updated the policy README to include CAR, highlighting its benefits and when to use it. - Removed outdated CAR roadmap documentation to streamline policy references.
1 parent 27f3c65 commit 0cac4e3

6 files changed

Lines changed: 1509 additions & 29 deletions

File tree

docs/policies/README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ If you can only implement one “general purpose” policy for mixed workloads,
4545
| LRU-K | Scan-resistant recency | [LRU-K doc](lru-k.md) |
4646
| 2Q | Probation + protected queues | [2Q doc](2q.md) |
4747
| ARC | Adaptive recency/frequency balance | [ARC doc](arc.md) |
48+
| CAR | ARC-like with Clock (lower hit overhead) | [CAR doc](car.md) |
4849
| FIFO | Simple insertion-order (oldest first) | [FIFO doc](fifo.md) |
4950
| LIFO | Stack-based (newest first) | [LIFO doc](lifo.md) |
5051
| Clock | Approximate LRU | [Clock doc](clock.md) |
@@ -55,7 +56,7 @@ If you can only implement one “general purpose” policy for mixed workloads,
5556

5657
### Roadmap Policies (Planned)
5758

58-
See [Policy roadmap](roadmap/README.md) for upcoming policies (ARC, CAR, LIRS, etc.).
59+
See [Policy roadmap](roadmap/README.md) for upcoming policies (LIRS, GDSF, etc.).
5960

6061
### Implemented Policy Summaries (Short)
6162

@@ -70,6 +71,7 @@ See [Policy roadmap](roadmap/README.md) for upcoming policies (ARC, CAR, LIRS, e
7071
- **LRU-K**: Good scan resistance; more metadata per entry.
7172
- **2Q**: Simple scan resistance; requires queue sizing.
7273
- **ARC**: Adaptive recency/frequency balance; no manual tuning; more metadata overhead.
74+
- **CAR**: ARC-like adaptivity with Clock; hits set ref bit only; scan-resistant.
7375
- **FIFO**: Predictable insertion order (oldest first); weak under strong locality.
7476
- **LIFO**: Stack order (newest first); niche use for undo buffers.
7577
- **Clock-PRO**: Scan-resistant Clock variant; more complexity.
@@ -80,10 +82,10 @@ For broader policy taxonomy (OPT, ARC, CAR, LIRS, Random, etc.), use the
8082

8183
## Practical Tradeoffs (What Changes In Real Systems)
8284

83-
- **Scan resistance**: `LRU`/`Clock` are vulnerable; `S3-FIFO`, `Heap-LFU`, `LRU-K`, `2Q`, and `ARC` handle scans better.
84-
- **Metadata & CPU**: `Random`/`FIFO` < `Clock` < `LRU` < `2Q`/`SLRU` < `LRU-K`/`ARC`/`LIRS`.
85+
- **Scan resistance**: `LRU`/`Clock` are vulnerable; `S3-FIFO`, `Heap-LFU`, `LRU-K`, `2Q`, `ARC`, and `CAR` handle scans better.
86+
- **Metadata & CPU**: `Random`/`FIFO` < `Clock` < `LRU` < `2Q`/`SLRU` < `LRU-K`/`ARC`/`CAR`/`LIRS`.
8587
- **Concurrency**: strict global `LRU` lists can contend; `Clock` and sharded designs often scale better.
86-
- **Adaptivity**: `LFU` needs decay to adapt; `ARC`-family adapts via history; static partitions (`2Q`/`SLRU`) need tuning.
88+
- **Adaptivity**: `LFU` needs decay to adapt; `ARC`/`CAR` adapt via history; static partitions (`2Q`/`SLRU`) need tuning.
8789
- **Predictability**: simpler policies are easier to reason about under tail-latency constraints; complex policies can have more edge cases.
8890

8991
## When To Use / Not Use (Rules Of Thumb)

docs/policies/car.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# CAR (Clock with Adaptive Replacement)
2+
3+
## Status
4+
5+
**Implemented** in `src/policy/car.rs`
6+
7+
## Goal
8+
9+
ARC-like adaptivity with Clock mechanics to reduce list manipulation overhead.
10+
Hits only set a reference bit instead of moving entries in linked lists,
11+
improving concurrency and cache-friendliness.
12+
13+
## Core Idea
14+
15+
Replace ARC's LRU lists with Clock structures plus ghost history:
16+
17+
- Two Clock rings for resident sets: **Recent** (seen once) and **Frequent** (repeated access)
18+
- Reference bits approximate recency within each set
19+
- ARC-like feedback from ghost hits adjusts `target_recent_size` (the adaptation parameter)
20+
- On hit: set ref bit only (no list move)
21+
- On eviction: sweep with clock hand, ref=0 evict, ref=1 clear and continue
22+
23+
## Core Data Structures
24+
25+
- `HashMap<K, usize>` for key → slot index
26+
- Single slot array with metadata: key, value, referenced bit, `Ring` (Recent/Frequent)
27+
- Two clock hands (`hand_recent`, `hand_frequent`) walking per-ring intrusive circular lists
28+
- Ghost lists `ghost_recent`, `ghost_frequent` (keys only) via `GhostList<K>`
29+
30+
## Key Operations (High Level)
31+
32+
### Get Operation
33+
34+
- Hit in Recent or Frequent ring: set `referenced = true`, return value (no list move)
35+
- Miss: not in cache (see insert for ghost hit handling)
36+
37+
### Insert Operation
38+
39+
- Key in cache: update value, set ref, return old value
40+
- Ghost hit in `ghost_recent`: adapt (increase `target_recent_size`), evict if needed, insert into Frequent ring
41+
- Ghost hit in `ghost_frequent`: adapt (decrease `target_recent_size`), evict if needed, insert into Frequent ring
42+
- Miss: evict if full (replace step), insert into Recent ring
43+
44+
### Replacement Step
45+
46+
Loop until one entry is evicted:
47+
48+
- If `|Recent| > target_recent_size`: sweep the Recent ring
49+
- Ref=0: evict to `ghost_recent`, done
50+
- Ref=1: demote to Frequent ring (clear ref), continue
51+
- If `|Recent| ≤ target_recent_size`: sweep the Frequent ring
52+
- Ref=0: evict to `ghost_frequent`, done
53+
- Ref=1: clear ref, advance hand, continue
54+
55+
### Adaptation
56+
57+
Same as ARC: ghost hit in `ghost_recent` increases `target_recent_size`;
58+
ghost hit in `ghost_frequent` decreases it.
59+
60+
## Complexity & Overhead
61+
62+
- O(1) get (hash lookup + bit set)
63+
- O(1) amortized insert
64+
- More metadata than plain Clock due to ghost lists and dual rings
65+
- Lower overhead than ARC on hits (no list moves)
66+
67+
## Example Usage
68+
69+
```rust
70+
use cachekit::policy::car::CARCore;
71+
use cachekit::traits::{CoreCache, ReadOnlyCache};
72+
73+
let mut cache = CARCore::new(100);
74+
cache.insert("page1", "content1");
75+
cache.insert("page2", "content2");
76+
assert_eq!(cache.get(&"page1"), Some(&"content1"));
77+
println!("recent: {}, frequent: {}, target: {}", cache.recent_len(), cache.frequent_len(), cache.target_recent_size());
78+
```
79+
80+
## When To Use
81+
82+
- Mixed workloads with unknown recency/frequency balance
83+
- Need scan resistance (ghost lists) like ARC
84+
- Prefer lower hit overhead than ARC (bit set vs list move)
85+
- Concurrency-friendly hit path
86+
87+
## When NOT To Use
88+
89+
- Simple temporal locality (Clock or LRU are simpler)
90+
- Memory-constrained (ghost lists add overhead)
91+
- Known workload where tuned 2Q/SLRU suffices
92+
93+
## Performance Characteristics
94+
95+
| Metric | Value |
96+
|----------|------------------|
97+
| Get | O(1) |
98+
| Insert | O(1) amortized |
99+
| Remove | O(1) |
100+
| Space | O(n) + ghost keys|
101+
| Scan res | High |
102+
| Adaptivity | Self-tuning |
103+
104+
## Implementation Notes
105+
106+
- Uses single slot array; Recent/Frequent are per-ring intrusive circular linked lists with separate hands
107+
- Demotion from Recent to Frequent clears ref bit (per CAR paper)
108+
- Ghost lists bounded to `capacity` each
109+
- `target_recent_size` starts at `capacity / 2`
110+
111+
## References
112+
113+
- Bansal & Modha, "CAR: Clock with Adaptive Replacement", FAST 2004
114+
- Wikipedia: https://en.wikipedia.org/wiki/Cache_replacement_policies

docs/policies/roadmap/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ If a policy moves into production code, its document should be moved back to
99

1010
## Roadmap Policies
1111

12-
- [CAR](car.md)
1312
- [GDSF](gdsf.md)
1413
- [LFU Aging](lfu-aging.md)
1514
- [LIRS](lirs.md)

docs/policies/roadmap/car.md

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)