Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions src/ds/intrusive_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,11 +871,10 @@ impl<T> IntrusiveList<T> {
#[inline]
fn attach_front(&mut self, id: SlotId) -> Option<()> {
let old_head = self.head;
if let Some(node) = self.arena.get_mut(id) {
{
let node = self.arena.get_mut(id)?;
node.prev = None;
node.next = old_head;
} else {
return None;
}
if let Some(old_head) = old_head {
if let Some(head_node) = self.arena.get_mut(old_head) {
Expand All @@ -891,11 +890,10 @@ impl<T> IntrusiveList<T> {
#[inline]
fn attach_back(&mut self, id: SlotId) -> Option<()> {
let old_tail = self.tail;
if let Some(node) = self.arena.get_mut(id) {
{
let node = self.arena.get_mut(id)?;
node.next = None;
node.prev = old_tail;
} else {
return None;
}
if let Some(old_tail) = old_tail {
if let Some(tail_node) = self.arena.get_mut(old_tail) {
Expand Down
17 changes: 9 additions & 8 deletions tests/abstract_models/reference/lfu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! **Source:** [`docs/testing/specs/policies/exact/lfu.md`](../../../docs/testing/specs/policies/exact/lfu.md) ·
//! [matrix.md](../../../docs/testing/specs/matrix.md)
//! **Tier:** reference (spec-first oracle).
//! **Formulation:** `HashMap<K, u64>` + append-only `first_seen` log for FIFO tie-break;
//! **Formulation:** `HashMap<K, u64>` + append-only bucket-arrival log for FIFO tie-break;
//! independent of [`FrequencyBuckets`](cachekit::ds::FrequencyBuckets).

use std::collections::{HashMap, HashSet, VecDeque};
Expand All @@ -14,7 +14,7 @@ use crate::abstract_models::{HitMiss, ModelStep, Op, OracleExpectation, PolicyMo
#[derive(Debug, Clone)]
pub struct NaiveLfuModel<K> {
freq: HashMap<K, u64>,
first_seen: VecDeque<K>,
bucket_arrivals: VecDeque<K>,
capacity: usize,
}

Expand All @@ -25,7 +25,7 @@ where
pub fn new(capacity: usize) -> Self {
Self {
freq: HashMap::new(),
first_seen: VecDeque::new(),
bucket_arrivals: VecDeque::new(),
capacity,
}
}
Expand All @@ -42,9 +42,9 @@ where
self.freq.values().copied().min()
}

/// Last append index for `key` in the tie-break log (re-inserts append again).
fn last_seen_index(&self, key: &K) -> usize {
self.first_seen
/// Last bucket-arrival index for `key` (touches and re-inserts append again).
fn bucket_arrival_index(&self, key: &K) -> usize {
self.bucket_arrivals
.iter()
.rposition(|k| k == key)
.unwrap_or(usize::MAX)
Expand All @@ -56,7 +56,7 @@ where
.iter()
.filter(|(_, f)| **f == min)
.map(|(k, _)| k)
.min_by_key(|k| self.last_seen_index(k))
.min_by_key(|k| self.bucket_arrival_index(k))
.cloned()
}

Expand All @@ -69,6 +69,7 @@ where
fn touch(&mut self, key: &K) -> bool {
if let Some(f) = self.freq.get_mut(key) {
*f = f.saturating_add(1);
self.bucket_arrivals.push_back(key.clone());
true
} else {
false
Expand All @@ -84,7 +85,7 @@ where
evicted = self.evict_victim();
}
self.freq.insert(key.clone(), 1);
self.first_seen.push_back(key);
self.bucket_arrivals.push_back(key);
evicted
}

Expand Down
14 changes: 14 additions & 0 deletions tests/policy_semantics/lfu_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ fn smoke_lfu_naive_agreement() {
assert_models_agree(&mut naive, &mut current, &ops);
}

#[test]
fn lfu_naive_agreement_uses_bucket_arrival_for_ties() {
let ops = [
Op::Insert(1),
Op::Insert(2),
Op::Touch(2),
Op::Touch(1),
Op::EvictOne,
];
let mut naive = NaiveLfuModel::new(2);
let mut current = LfuModel::new(2);
assert_models_agree(&mut naive, &mut current, &ops);
}

#[test]
fn smoke_lfu() {
let ops = [
Expand Down
Loading