Repository navigation
dp/page_replacement: update FIFO to PersistentQueue and LRU to index map - #49
Merged
Merged
Conversation
- FIFO: replace O(f) vector-copying (vec (rest q)) with PersistentQueue (O(1) amortized peek/pop/conj). - LRU: replace O(f) vector scans (some #(= % p) lru) and deletions with timestamp-indexed hash-map + sorted-set (O(log f) amortized per ref). - Marking: drive loop by index i instead of lazy (rest rs) sequences. Brings FIFO and LRU asymptotic complexity into parity with the Python twin. Verified against all 4 shared test cases + 50 randomized differential tests against Python + 80 pytest cases across all languages.
|
| Project | clojure-code-snippet |
| Branch | fix/page-replacement-complexity |
| Commit | 6bb702a |
| Report | Testbed | Adapter | Status |
|---|---|---|---|
| 1 | ubuntu-latest-clojure-rs | JSON | ✅ No Alerts |
| 2 | ubuntu-latest-jvm | JSON | ✅ No Alerts |
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
michael-h-hu
approved these changes
Nov 4, 2026
michael-h-hu
left a comment
Collaborator
There was a problem hiding this comment.
Review: PR #49 — dp/page_replacement FIFO/LRU complexity fix
Verdict: no findings — approve
What was inspected
- Full diff of
src/dp/page_replacement/page_replacement.clj(only file changed)
plus the pre-image frommasterfor old-vs-new comparison. gh pr checks 49: every check green (test shards 1–4, perf-callgrind
jvm + clojure-rs legs, report, resolve-rs).- No call sites: snippet is a standalone stdin/stdout program; no other
repo code depends on its internals.
Correctness
- FIFO:
q []+(vec (rest q))eviction replaced by
clojure.lang.PersistentQueue/EMPTYwithpeek/pop/conj, keeping
thesmembership set. Queue/set stay in lockstep;pop/peekare
only reached when(count q) >= fwithf > 0, so never on an empty
queue.f <= 0short-circuit preserved. - LRU: vector scan/remove replaced by
p->tmap plussorted-setof
[t p]with strictly increasing timestamps, so ordering is total and
(first t-set)is always the least-recently-used page. Map and set are
updated together on hits, misses, and evictions; eviction branch is only
reachable with a non-empty set.f <= 0short-circuit preserved. - Marking loop: same eviction logic, only the driver changed from lazy
(rest rs)to indexioverrq— same sequence, no lazy-seq
retention. - Java interop is minimal and idiomatic: only the
PersistentQueue/EMPTYconstant; all ops are core fns.sorted-set
keeps LRU purely functional instead of reaching for a mutable
LinkedHashMap.
Complexity
- FIFO: O(m·f) → O(m) time (
peek/pop/conj/countall O(1)
amortized on PersistentQueue); space stays O(f). - LRU: O(m·f) → O(m·log f) time (map ops plus sorted-set
conj/disj/first); space stays O(f). O(log f) rather than the
Python twin's O(1) is the right tradeoff for a purely functional,
low-interop implementation. - Marking: unchanged asymptotics; index driving only trims constant
overhead.
Verification run
- 26 hand-built old-vs-new differential cases through JVM Clojure
(basic, classic reference strings, f=0/negative/1, m=0, all-same,
all-distinct, negative/large page ids, Belady sequences, cyclic and
thrash patterns, plus 2000- and 5000-ref pseudo-random inputs): all
byte-identical, including the marking line. Belady's anomaly still
reproduces (FIFO f=3 faults 9 < f=4 faults 10), confirming FIFO
semantics survived the refactor. - One 20k-ref input: identical output on both versions.
Residual risks / gaps
- None blocking. Worst case worth noting: none of the differential
inputs exceed ~20k refs locally, but CI's full gate (incl. perf legs)
is green on this HEAD.
AI-Tool: Muse Code (Meta Muse Spark)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Updates
dp/page_replacement/page_replacement.cljto bring its FIFO and LRU algorithms into complexity parity with its Python twin:(vec (rest q))((f)$ per eviction) withclojure.lang.PersistentQueue((1)$ amortizedpeek,pop, andconj). Total FIFO time drops from (m \cdot f)$ to (m)$.(some #(= % p) lru)and vector removals ((f)$ per ref) with a timestamp-indexed hash-mapp->tand a sorted set of[t p]timestamps. Per-ref operations drop to (\log f)$ amortized.iinstead of lazy(rest rs)sequences.Validation
resource/shared/dp/page_replacement/page_replacementpass byte-identically.python-code-snippetpass byte-identically across varying $ and $.problem_test/dp/page_replacement).