Skip to content

Commit

Permalink
refactor: wrapper no/immutable/mutable op into Op (#788)
Browse files Browse the repository at this point in the history
Signed-off-by: MrCroxx <[email protected]>
  • Loading branch information
MrCroxx authored Nov 19, 2024
1 parent d633ae2 commit f9ac2f9
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 230 deletions.
34 changes: 9 additions & 25 deletions foyer-memory/src/eviction/fifo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use foyer_common::code::{Key, Value};
use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListAtomicLink};
use serde::{Deserialize, Serialize};

use super::{Eviction, Operator};
use super::{Eviction, Op};
use crate::record::{CacheHint, Record};

/// Fifo eviction algorithm config.
Expand Down Expand Up @@ -93,28 +93,12 @@ where
record.set_in_eviction(false);
}

fn acquire_operator() -> super::Operator {
Operator::Noop
fn acquire() -> Op<Self> {
Op::noop()
}

fn acquire_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn acquire_mutable(&mut self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn release_operator() -> super::Operator {
Operator::Noop
}

fn release_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn release_mutable(&mut self, _record: &Arc<Record<Self>>) {
unreachable!()
fn release() -> Op<Self> {
Op::noop()
}
}

Expand All @@ -125,17 +109,17 @@ pub mod tests {

use super::*;
use crate::{
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_eq, TestEviction},
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_eq, Dump},
record::Data,
};

impl<K, V> TestEviction for Fifo<K, V>
impl<K, V> Dump for Fifo<K, V>
where
K: Key + Clone,
V: Value + Clone,
{
type Dump = Vec<Arc<Record<Self>>>;
fn dump(&self) -> Self::Dump {
type Output = Vec<Arc<Record<Self>>>;
fn dump(&self) -> Self::Output {
let mut res = vec![];
let mut cursor = self.queue.cursor();
loop {
Expand Down
109 changes: 47 additions & 62 deletions foyer-memory/src/eviction/lfu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use foyer_common::{
use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListAtomicLink};
use serde::{Deserialize, Serialize};

use super::{Eviction, Operator};
use super::{Eviction, Op};
use crate::record::{CacheHint, Record};

/// w-TinyLFU eviction algorithm config.
Expand Down Expand Up @@ -347,71 +347,56 @@ where
}
}

fn acquire_operator() -> super::Operator {
// TODO(MrCroxx): use a count-min-sketch with atomic u16 impl.
Operator::Mutable
}

fn acquire_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn acquire_mutable(&mut self, record: &Arc<Record<Self>>) {
// Update frequency by access.
self.update_frequencies(record.hash());
fn acquire() -> Op<Self> {
Op::mutable(|this: &mut Self, record| {
// Update frequency by access.
this.update_frequencies(record.hash());

if !record.is_in_eviction() {
return;
}
if !record.is_in_eviction() {
return;
}

let state = unsafe { &mut *record.state().get() };
let state = unsafe { &mut *record.state().get() };

strict_assert!(state.link.is_linked());
strict_assert!(state.link.is_linked());

match state.queue {
Queue::None => unreachable!(),
Queue::Window => {
// Move to MRU position of `window`.
let r = unsafe { self.window.remove_from_ptr(Arc::as_ptr(record)) };
self.window.push_back(r);
}
Queue::Probation => {
// Promote to MRU position of `protected`.
let r = unsafe { self.probation.remove_from_ptr(Arc::as_ptr(record)) };
self.decrease_queue_weight(Queue::Probation, record.weight());
state.queue = Queue::Protected;
self.increase_queue_weight(Queue::Protected, record.weight());
self.protected.push_back(r);

// If `protected` weight exceeds the capacity, overflow entry from `protected` to `probation`.
while self.protected_weight > self.protected_weight_capacity {
strict_assert!(!self.protected.is_empty());
let r = self.protected.pop_front().unwrap();
let s = unsafe { &mut *r.state().get() };
self.decrease_queue_weight(Queue::Protected, r.weight());
s.queue = Queue::Probation;
self.increase_queue_weight(Queue::Probation, r.weight());
self.probation.push_back(r);
match state.queue {
Queue::None => unreachable!(),
Queue::Window => {
// Move to MRU position of `window`.
let r = unsafe { this.window.remove_from_ptr(Arc::as_ptr(record)) };
this.window.push_back(r);
}
Queue::Probation => {
// Promote to MRU position of `protected`.
let r = unsafe { this.probation.remove_from_ptr(Arc::as_ptr(record)) };
this.decrease_queue_weight(Queue::Probation, record.weight());
state.queue = Queue::Protected;
this.increase_queue_weight(Queue::Protected, record.weight());
this.protected.push_back(r);

// If `protected` weight exceeds the capacity, overflow entry from `protected` to `probation`.
while this.protected_weight > this.protected_weight_capacity {
strict_assert!(!this.protected.is_empty());
let r = this.protected.pop_front().unwrap();
let s = unsafe { &mut *r.state().get() };
this.decrease_queue_weight(Queue::Protected, r.weight());
s.queue = Queue::Probation;
this.increase_queue_weight(Queue::Probation, r.weight());
this.probation.push_back(r);
}
}
Queue::Protected => {
// Move to MRU position of `protected`.
let r = unsafe { this.protected.remove_from_ptr(Arc::as_ptr(record)) };
this.protected.push_back(r);
}
}
Queue::Protected => {
// Move to MRU position of `protected`.
let r = unsafe { self.protected.remove_from_ptr(Arc::as_ptr(record)) };
self.protected.push_back(r);
}
}
}

fn release_operator() -> Operator {
Operator::Noop
}

fn release_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
})
}

fn release_mutable(&mut self, _record: &Arc<Record<Self>>) {
unreachable!()
fn release() -> Op<Self> {
Op::noop()
}
}

Expand All @@ -422,17 +407,17 @@ mod tests {

use super::*;
use crate::{
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_vec_eq, TestEviction},
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_vec_eq, Dump, OpExt},
record::Data,
};

impl<K, V> TestEviction for Lfu<K, V>
impl<K, V> Dump for Lfu<K, V>
where
K: Key + Clone,
V: Value + Clone,
{
type Dump = Vec<Vec<Arc<Record<Self>>>>;
fn dump(&self) -> Self::Dump {
type Output = Vec<Vec<Arc<Record<Self>>>>;
fn dump(&self) -> Self::Output {
let mut window = vec![];
let mut probation = vec![];
let mut protected = vec![];
Expand Down
98 changes: 43 additions & 55 deletions foyer-memory/src/eviction/lru.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use foyer_common::{
use intrusive_collections::{intrusive_adapter, LinkedList, LinkedListAtomicLink};
use serde::{Deserialize, Serialize};

use super::{Eviction, Operator};
use super::{Eviction, Op};
use crate::record::{CacheHint, Record};

/// Lru eviction algorithm config.
Expand Down Expand Up @@ -248,70 +248,58 @@ where
assert_eq!(self.high_priority_weight, 0);
}

fn acquire_operator() -> super::Operator {
Operator::Mutable
}

fn acquire_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn acquire_mutable(&mut self, record: &Arc<Record<Self>>) {
if !record.is_in_eviction() {
return;
}

let state = unsafe { &mut *record.state().get() };
assert!(state.link.is_linked());
fn acquire() -> Op<Self> {
Op::mutable(|this: &mut Self, record| {
if !record.is_in_eviction() {
return;
}

if state.is_pinned {
return;
}
let state = unsafe { &mut *record.state().get() };
assert!(state.link.is_linked());

// Pin the record by moving it to the pin list.
if state.is_pinned {
return;
}

let r = if state.in_high_priority_pool {
unsafe { self.high_priority_list.remove_from_ptr(Arc::as_ptr(record)) }
} else {
unsafe { self.list.remove_from_ptr(Arc::as_ptr(record)) }
};
// Pin the record by moving it to the pin list.

self.pin_list.push_back(r);
let r = if state.in_high_priority_pool {
unsafe { this.high_priority_list.remove_from_ptr(Arc::as_ptr(record)) }
} else {
unsafe { this.list.remove_from_ptr(Arc::as_ptr(record)) }
};

state.is_pinned = true;
}
this.pin_list.push_back(r);

fn release_operator() -> Operator {
Operator::Mutable
state.is_pinned = true;
})
}

fn release_immutable(&self, _record: &Arc<Record<Self>>) {
unreachable!()
}

fn release_mutable(&mut self, record: &Arc<Record<Self>>) {
if !record.is_in_eviction() {
return;
}
fn release() -> Op<Self> {
Op::mutable(|this: &mut Self, record| {
if !record.is_in_eviction() {
return;
}

let state = unsafe { &mut *record.state().get() };
assert!(state.link.is_linked());
let state = unsafe { &mut *record.state().get() };
assert!(state.link.is_linked());

if !state.is_pinned {
return;
}
if !state.is_pinned {
return;
}

// Unpin the record by moving it from the pin list.
// Unpin the record by moving it from the pin list.

unsafe { self.pin_list.remove_from_ptr(Arc::as_ptr(record)) };
unsafe { this.pin_list.remove_from_ptr(Arc::as_ptr(record)) };

if state.in_high_priority_pool {
self.high_priority_list.push_back(record.clone());
} else {
self.list.push_back(record.clone());
}
if state.in_high_priority_pool {
this.high_priority_list.push_back(record.clone());
} else {
this.list.push_back(record.clone());
}

state.is_pinned = false;
state.is_pinned = false;
})
}
}

Expand All @@ -322,17 +310,17 @@ pub mod tests {

use super::*;
use crate::{
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_vec_eq, TestEviction},
eviction::test_utils::{assert_ptr_eq, assert_ptr_vec_vec_eq, Dump, OpExt},
record::Data,
};

impl<K, V> TestEviction for Lru<K, V>
impl<K, V> Dump for Lru<K, V>
where
K: Key + Clone,
V: Value + Clone,
{
type Dump = Vec<Vec<Arc<Record<Self>>>>;
fn dump(&self) -> Self::Dump {
type Output = Vec<Vec<Arc<Record<Self>>>>;
fn dump(&self) -> Self::Output {
let mut low = vec![];
let mut high = vec![];
let mut pin = vec![];
Expand Down
Loading

0 comments on commit f9ac2f9

Please sign in to comment.