From c51d2483bbe227157cabdca61f52c2880d3905ac Mon Sep 17 00:00:00 2001 From: Croxx Date: Sat, 20 Apr 2024 15:20:39 +0800 Subject: [PATCH] fix: assert handle weight and refactor handle (#380) * fix: assert handle weight and refactor handle Signed-off-by: MrCroxx * chore: rename charge to weight Signed-off-by: MrCroxx --------- Signed-off-by: MrCroxx --- foyer-memory/src/cache.rs | 10 +-- foyer-memory/src/eviction/fifo.rs | 21 +++--- foyer-memory/src/eviction/lfu.rs | 101 ++++++++++++++-------------- foyer-memory/src/eviction/lru.rs | 65 +++++++++--------- foyer-memory/src/eviction/s3fifo.rs | 49 +++++++------- foyer-memory/src/generic.rs | 41 ++++++----- foyer-memory/src/handle.rs | 31 +++++---- foyer-memory/src/listener.rs | 4 +- 8 files changed, 164 insertions(+), 158 deletions(-) diff --git a/foyer-memory/src/cache.rs b/foyer-memory/src/cache.rs index 4bae5052..691222d0 100644 --- a/foyer-memory/src/cache.rs +++ b/foyer-memory/src/cache.rs @@ -200,12 +200,12 @@ where } } - pub fn charge(&self) -> usize { + pub fn weight(&self) -> usize { match self { - CacheEntry::Fifo(entry) => entry.charge(), - CacheEntry::Lru(entry) => entry.charge(), - CacheEntry::Lfu(entry) => entry.charge(), - CacheEntry::S3Fifo(entry) => entry.charge(), + CacheEntry::Fifo(entry) => entry.weight(), + CacheEntry::Lru(entry) => entry.weight(), + CacheEntry::Lfu(entry) => entry.weight(), + CacheEntry::S3Fifo(entry) => entry.weight(), } } diff --git a/foyer-memory/src/eviction/fifo.rs b/foyer-memory/src/eviction/fifo.rs index 85144490..c90c452d 100644 --- a/foyer-memory/src/eviction/fifo.rs +++ b/foyer-memory/src/eviction/fifo.rs @@ -59,23 +59,24 @@ where intrusive_adapter! { FifoHandleDlistAdapter = NonNull>: FifoHandle { link: DlistLink } where T: Send + Sync + 'static } -impl Handle for FifoHandle +impl Default for FifoHandle where T: Send + Sync + 'static, { - type Data = T; - type Context = FifoContext; - - fn new() -> Self { + fn default() -> Self { Self { link: DlistLink::default(), base: BaseHandle::new(), } } +} - fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context) { - self.base.init(hash, data, charge, context); - } +impl Handle for FifoHandle +where + T: Send + Sync + 'static, +{ + type Data = T; + type Context = FifoContext; fn base(&self) -> &BaseHandle { &self.base @@ -159,7 +160,7 @@ pub mod tests { use itertools::Itertools; use super::*; - use crate::eviction::test_utils::TestEviction; + use crate::{eviction::test_utils::TestEviction, handle::HandleExt}; impl TestEviction for Fifo where @@ -177,7 +178,7 @@ pub mod tests { type TestFifo = Fifo; unsafe fn new_test_fifo_handle_ptr(data: u64) -> NonNull { - let mut handle = Box::new(TestFifoHandle::new()); + let mut handle = Box::::default(); handle.init(0, data, 1, FifoContext); NonNull::new_unchecked(Box::into_raw(handle)) } diff --git a/foyer-memory/src/eviction/lfu.rs b/foyer-memory/src/eviction/lfu.rs index 03946ae9..bd527396 100644 --- a/foyer-memory/src/eviction/lfu.rs +++ b/foyer-memory/src/eviction/lfu.rs @@ -88,24 +88,25 @@ where intrusive_adapter! { LfuHandleDlistAdapter = NonNull>: LfuHandle { link: DlistLink } where T: Send + Sync + 'static } -impl Handle for LfuHandle +impl Default for LfuHandle where T: Send + Sync + 'static, { - type Data = T; - type Context = LfuContext; - - fn new() -> Self { + fn default() -> Self { Self { link: DlistLink::default(), base: BaseHandle::new(), queue: Queue::None, } } +} - fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context) { - self.base.init(hash, data, charge, context) - } +impl Handle for LfuHandle +where + T: Send + Sync + 'static, +{ + type Data = T; + type Context = LfuContext; fn base(&self) -> &BaseHandle { &self.base @@ -139,12 +140,12 @@ where probation: Dlist>, protected: Dlist>, - window_charges: usize, - probation_charges: usize, - protected_charges: usize, + window_weight: usize, + probation_weight: usize, + protected_weight: usize, - window_charges_capacity: usize, - protected_charges_capacity: usize, + window_weight_capacity: usize, + protected_weight_capacity: usize, frequencies: CMSketchU16, @@ -156,23 +157,23 @@ impl Lfu where T: Send + Sync + 'static, { - fn increase_queue_charges(&mut self, handle: &LfuHandle) { - let charges = handle.base().charge(); + fn increase_queue_weight(&mut self, handle: &LfuHandle) { + let weight = handle.base().weight(); match handle.queue { Queue::None => unreachable!(), - Queue::Window => self.window_charges += charges, - Queue::Probation => self.probation_charges += charges, - Queue::Protected => self.protected_charges += charges, + Queue::Window => self.window_weight += weight, + Queue::Probation => self.probation_weight += weight, + Queue::Protected => self.protected_weight += weight, } } - fn decrease_queue_charges(&mut self, handle: &LfuHandle) { - let charges = handle.base().charge(); + fn decrease_queue_weight(&mut self, handle: &LfuHandle) { + let weight = handle.base().weight(); match handle.queue { Queue::None => unreachable!(), - Queue::Window => self.window_charges -= charges, - Queue::Probation => self.probation_charges -= charges, - Queue::Protected => self.protected_charges -= charges, + Queue::Window => self.window_weight -= weight, + Queue::Probation => self.probation_weight -= weight, + Queue::Protected => self.protected_weight -= weight, } } @@ -215,8 +216,8 @@ where config.window_capacity_ratio + config.protected_capacity_ratio ); - let window_charges_capacity = (capacity as f64 * config.window_capacity_ratio) as usize; - let protected_charges_capacity = (capacity as f64 * config.protected_capacity_ratio) as usize; + let window_weight_capacity = (capacity as f64 * config.window_capacity_ratio) as usize; + let protected_weight_capacity = (capacity as f64 * config.protected_capacity_ratio) as usize; let frequencies = CMSketchU16::new(config.cmsketch_eps, config.cmsketch_confidence); let decay = frequencies.width(); @@ -224,11 +225,11 @@ where window: Dlist::new(), probation: Dlist::new(), protected: Dlist::new(), - window_charges: 0, - probation_charges: 0, - protected_charges: 0, - window_charges_capacity, - protected_charges_capacity, + window_weight: 0, + probation_weight: 0, + protected_weight: 0, + window_weight_capacity, + protected_weight_capacity, frequencies, step: 0, decay, @@ -246,17 +247,17 @@ where handle.base_mut().set_in_eviction(true); handle.queue = Queue::Window; - self.increase_queue_charges(handle); + self.increase_queue_weight(handle); self.update_frequencies(handle.base().hash()); - // If `window` charges exceeds the capacity, overflow entry from `window` to `probation`. - while self.window_charges > self.window_charges_capacity { + // If `window` weight exceeds the capacity, overflow entry from `window` to `probation`. + while self.window_weight > self.window_weight_capacity { debug_assert!(!self.window.is_empty()); let mut ptr = self.window.pop_front().unwrap_unchecked(); let handle = ptr.as_mut(); - self.decrease_queue_charges(handle); + self.decrease_queue_weight(handle); handle.queue = Queue::Probation; - self.increase_queue_charges(handle); + self.increase_queue_weight(handle); self.probation.push_back(ptr); } } @@ -288,7 +289,7 @@ where debug_assert!(handle.base().is_in_eviction()); debug_assert_ne!(handle.queue, Queue::None); - self.decrease_queue_charges(handle); + self.decrease_queue_weight(handle); handle.queue = Queue::None; handle.base_mut().set_in_eviction(false); @@ -318,19 +319,19 @@ where debug_assert!(handle.link.is_linked()); debug_assert!(handle.base().is_in_eviction()); self.probation.remove_raw(handle.link.raw()); - self.decrease_queue_charges(handle); + self.decrease_queue_weight(handle); handle.queue = Queue::Protected; - self.increase_queue_charges(handle); + self.increase_queue_weight(handle); self.protected.push_back(ptr); - // If `protected` charges exceeds the capacity, overflow entry from `protected` to `probation`. - while self.protected_charges > self.protected_charges_capacity { + // If `protected` weight exceeds the capacity, overflow entry from `protected` to `probation`. + while self.protected_weight > self.protected_weight_capacity { debug_assert!(!self.protected.is_empty()); let mut ptr = self.protected.pop_front().unwrap_unchecked(); let handle = ptr.as_mut(); - self.decrease_queue_charges(handle); + self.decrease_queue_weight(handle); handle.queue = Queue::Probation; - self.increase_queue_charges(handle); + self.increase_queue_weight(handle); self.probation.push_back(ptr); } } @@ -364,7 +365,7 @@ where debug_assert!(!handle.link.is_linked()); - self.decrease_queue_charges(handle); + self.decrease_queue_weight(handle); handle.queue = Queue::None; handle.base_mut().set_in_eviction(false); } @@ -401,7 +402,7 @@ mod tests { use itertools::Itertools; use super::*; - use crate::eviction::test_utils::TestEviction; + use crate::{eviction::test_utils::TestEviction, handle::HandleExt}; impl TestEviction for Lfu where @@ -432,9 +433,9 @@ mod tests { assert_eq!(lfu.window.len(), window); assert_eq!(lfu.probation.len(), probation); assert_eq!(lfu.protected.len(), protected); - assert_eq!(lfu.window_charges, window); - assert_eq!(lfu.probation_charges, probation); - assert_eq!(lfu.protected_charges, protected); + assert_eq!(lfu.window_weight, window); + assert_eq!(lfu.probation_weight, probation); + assert_eq!(lfu.protected_weight, protected); let es = lfu.dump().into_iter().collect_vec(); assert_eq!(es, entries); } @@ -449,7 +450,7 @@ mod tests { unsafe { let ptrs = (0..100) .map(|i| { - let mut handle = Box::new(TestLfuHandle::new()); + let mut handle = Box::::default(); handle.init(i, i, 1, LfuContext); NonNull::new_unchecked(Box::into_raw(handle)) }) @@ -464,8 +465,8 @@ mod tests { }; let mut lfu = TestLfu::new(10, &config); - assert_eq!(lfu.window_charges_capacity, 2); - assert_eq!(lfu.protected_charges_capacity, 6); + assert_eq!(lfu.window_weight_capacity, 2); + assert_eq!(lfu.protected_weight_capacity, 6); lfu.push(ptrs[0]); lfu.push(ptrs[1]); diff --git a/foyer-memory/src/eviction/lru.rs b/foyer-memory/src/eviction/lru.rs index ba0cb228..0ce126d4 100644 --- a/foyer-memory/src/eviction/lru.rs +++ b/foyer-memory/src/eviction/lru.rs @@ -30,7 +30,7 @@ use crate::{ pub struct LruConfig { /// The ratio of the high priority pool occupied. /// - /// [`Lru`] guarantees that the high priority charges are always as larger as + /// [`Lru`] guarantees that the high priority weight are always as larger as /// but no larger that the capacity * high priority pool ratio. /// /// # Panic @@ -83,24 +83,25 @@ where intrusive_adapter! { LruHandleDlistAdapter = NonNull>: LruHandle { link: DlistLink } where T: Send + Sync + 'static } -impl Handle for LruHandle +impl Default for LruHandle where T: Send + Sync + 'static, { - type Data = T; - type Context = LruContext; - - fn new() -> Self { + fn default() -> Self { Self { link: DlistLink::default(), base: BaseHandle::new(), in_high_priority_pool: false, } } +} - fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context) { - self.base.init(hash, data, charge, context) - } +impl Handle for LruHandle +where + T: Send + Sync + 'static, +{ + type Data = T; + type Context = LruContext; fn base(&self) -> &BaseHandle { &self.base @@ -121,8 +122,8 @@ where high_priority_list: Dlist>, list: Dlist>, - high_priority_charges: usize, - high_priority_charges_capacity: usize, + high_priority_weight: usize, + high_priority_weight_capacity: usize, } impl Lru @@ -130,13 +131,13 @@ where T: Send + Sync + 'static, { unsafe fn may_overflow_high_priority_pool(&mut self) { - while self.high_priority_charges > self.high_priority_charges_capacity { + while self.high_priority_weight > self.high_priority_weight_capacity { debug_assert!(!self.high_priority_list.is_empty()); // overflow last entry in high priority pool to low priority pool let mut ptr = self.high_priority_list.pop_front().unwrap_unchecked(); ptr.as_mut().in_high_priority_pool = false; - self.high_priority_charges -= ptr.as_ref().base().charge(); + self.high_priority_weight -= ptr.as_ref().base().weight(); self.list.push_back(ptr); } } @@ -159,13 +160,13 @@ where config.high_priority_pool_ratio ); - let high_priority_charges_capacity = (capacity as f64 * config.high_priority_pool_ratio) as usize; + let high_priority_weight_capacity = (capacity as f64 * config.high_priority_pool_ratio) as usize; Self { high_priority_list: Dlist::new(), list: Dlist::new(), - high_priority_charges: 0, - high_priority_charges_capacity, + high_priority_weight: 0, + high_priority_weight_capacity, } } @@ -177,7 +178,7 @@ where match handle.base().context() { LruContext::HighPriority => { handle.in_high_priority_pool = true; - self.high_priority_charges += handle.base().charge(); + self.high_priority_weight += handle.base().weight(); self.high_priority_list.push_back(ptr); self.may_overflow_high_priority_pool(); @@ -198,7 +199,7 @@ where debug_assert!(!handle.link.is_linked()); if handle.in_high_priority_pool { - self.high_priority_charges -= handle.base().charge(); + self.high_priority_weight -= handle.base().weight(); } handle.base_mut().set_in_eviction(false); @@ -226,7 +227,7 @@ where debug_assert!(handle.link.is_linked()); if handle.in_high_priority_pool { - self.high_priority_charges -= handle.base.charge(); + self.high_priority_weight -= handle.base.weight(); self.high_priority_list.remove_raw(handle.link.raw()); } else { self.list.remove_raw(handle.link.raw()); @@ -247,11 +248,11 @@ where while !self.high_priority_list.is_empty() { let mut ptr = self.high_priority_list.pop_front().unwrap_unchecked(); ptr.as_mut().base_mut().set_in_eviction(false); - self.high_priority_charges -= ptr.as_ref().base().charge(); + self.high_priority_weight -= ptr.as_ref().base().weight(); res.push(ptr); } - debug_assert_eq!(self.high_priority_charges, 0); + debug_assert_eq!(self.high_priority_weight, 0); res } @@ -275,7 +276,7 @@ pub mod tests { use itertools::Itertools; use super::*; - use crate::eviction::test_utils::TestEviction; + use crate::{eviction::test_utils::TestEviction, handle::HandleExt}; impl TestEviction for Lru where @@ -294,7 +295,7 @@ pub mod tests { type TestLru = Lru; unsafe fn new_test_lru_handle_ptr(data: u64, context: LruContext) -> NonNull { - let mut handle = Box::new(TestLruHandle::new()); + let mut handle = Box::::default(); handle.init(0, data, 1, context); NonNull::new_unchecked(Box::into_raw(handle)) } @@ -337,7 +338,7 @@ pub mod tests { }; let mut lru = TestLru::new(8, &config); - assert_eq!(lru.high_priority_charges_capacity, 4); + assert_eq!(lru.high_priority_weight_capacity, 4); // [0, 1, 2, 3] lru.push(ptrs[0]); @@ -345,14 +346,14 @@ pub mod tests { lru.push(ptrs[2]); lru.push(ptrs[3]); assert_eq!(lru.len(), 4); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!(dump_test_lru(&lru), (vec![], vec![ptrs[0], ptrs[1], ptrs[2], ptrs[3]])); // 0, [1, 2, 3, 4] lru.push(ptrs[4]); assert_eq!(lru.len(), 5); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!( dump_test_lru(&lru), @@ -362,7 +363,7 @@ pub mod tests { // 0, 10, [1, 2, 3, 4] lru.push(ptrs[10]); assert_eq!(lru.len(), 6); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!( dump_test_lru(&lru), @@ -373,7 +374,7 @@ pub mod tests { let p0 = lru.pop().unwrap(); assert_eq!(ptrs[0], p0); assert_eq!(lru.len(), 5); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!( dump_test_lru(&lru), @@ -383,14 +384,14 @@ pub mod tests { // 10, [1, 3, 4] lru.remove(ptrs[2]); assert_eq!(lru.len(), 4); - assert_eq!(lru.high_priority_charges, 3); + assert_eq!(lru.high_priority_weight, 3); assert_eq!(lru.high_priority_list.len(), 3); assert_eq!(dump_test_lru(&lru), (vec![ptrs[10]], vec![ptrs[1], ptrs[3], ptrs[4]])); // 10, 11, [1, 3, 4] lru.push(ptrs[11]); assert_eq!(lru.len(), 5); - assert_eq!(lru.high_priority_charges, 3); + assert_eq!(lru.high_priority_weight, 3); assert_eq!(lru.high_priority_list.len(), 3); assert_eq!( dump_test_lru(&lru), @@ -401,7 +402,7 @@ pub mod tests { lru.push(ptrs[5]); lru.push(ptrs[6]); assert_eq!(lru.len(), 7); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!( dump_test_lru(&lru), @@ -414,7 +415,7 @@ pub mod tests { // 10, 11, 1, 3, [4, 5, 6, 0] lru.push(ptrs[0]); assert_eq!(lru.len(), 8); - assert_eq!(lru.high_priority_charges, 4); + assert_eq!(lru.high_priority_weight, 4); assert_eq!(lru.high_priority_list.len(), 4); assert_eq!( dump_test_lru(&lru), diff --git a/foyer-memory/src/eviction/s3fifo.rs b/foyer-memory/src/eviction/s3fifo.rs index a34af8d0..c1d8fbec 100644 --- a/foyer-memory/src/eviction/s3fifo.rs +++ b/foyer-memory/src/eviction/s3fifo.rs @@ -87,14 +87,11 @@ where } } -impl Handle for S3FifoHandle +impl Default for S3FifoHandle where T: Send + Sync + 'static, { - type Data = T; - type Context = S3FifoContext; - - fn new() -> Self { + fn default() -> Self { Self { link: DlistLink::default(), freq: 0, @@ -102,10 +99,14 @@ where queue: Queue::None, } } +} - fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context) { - self.base.init(hash, data, charge, context); - } +impl Handle for S3FifoHandle +where + T: Send + Sync + 'static, +{ + type Data = T; + type Context = S3FifoContext; fn base(&self) -> &BaseHandle { &self.base @@ -130,8 +131,8 @@ where small_capacity: usize, - small_charges: usize, - main_charges: usize, + small_weight: usize, + main_weight: usize, } impl S3Fifo @@ -140,7 +141,7 @@ where { unsafe fn evict(&mut self) -> Option>> { // TODO(MrCroxx): Use `let_chains` here after it is stable. - if self.small_charges > self.small_capacity { + if self.small_weight > self.small_capacity { if let Some(ptr) = self.evict_small() { return Some(ptr); } @@ -154,12 +155,12 @@ where if handle.freq > 1 { self.main_queue.push_back(ptr); handle.queue = Queue::Main; - self.small_charges -= handle.base().charge(); - self.main_charges += handle.base().charge(); + self.small_weight -= handle.base().weight(); + self.main_weight += handle.base().weight(); } else { handle.queue = Queue::None; handle.reset(); - self.small_charges -= handle.base().charge(); + self.small_weight -= handle.base().weight(); return Some(ptr); } } @@ -174,7 +175,7 @@ where handle.dec(); } else { handle.queue = Queue::None; - self.main_charges -= handle.base.charge(); + self.main_weight -= handle.base.weight(); return Some(ptr); } } @@ -198,8 +199,8 @@ where small_queue: Dlist::new(), main_queue: Dlist::new(), small_capacity, - small_charges: 0, - main_charges: 0, + small_weight: 0, + main_weight: 0, } } @@ -208,7 +209,7 @@ where self.small_queue.push_back(ptr); handle.queue = Queue::Small; - self.small_charges += handle.base().charge(); + self.small_weight += handle.base().weight(); handle.base_mut().set_in_eviction(true); } @@ -248,7 +249,7 @@ where handle.queue = Queue::None; handle.base_mut().set_in_eviction(false); - self.main_charges -= handle.base().charge(); + self.main_weight -= handle.base().weight(); } Queue::Small => { let p = self @@ -261,7 +262,7 @@ where handle.queue = Queue::None; handle.base_mut().set_in_eviction(false); - self.small_charges -= handle.base().charge(); + self.small_weight -= handle.base().weight(); } } } @@ -302,7 +303,7 @@ mod tests { use itertools::Itertools; use super::*; - use crate::eviction::test_utils::TestEviction; + use crate::{eviction::test_utils::TestEviction, handle::HandleExt}; impl TestEviction for S3Fifo where @@ -325,7 +326,7 @@ mod tests { assert_eq!(s.len(), s3fifo.small_queue.len() + s3fifo.main_queue.len()); let m = s.split_off(s3fifo.small_queue.len()); assert_eq!((&s, &m), (&small, &main)); - assert_eq!(s3fifo.small_charges, s.len()); + assert_eq!(s3fifo.small_weight, s.len()); } fn assert_count(ptrs: &[NonNull], range: Range, count: u8) { @@ -335,11 +336,11 @@ mod tests { } #[test] - fn test_lfu() { + fn test_s3fifo() { unsafe { let ptrs = (0..100) .map(|i| { - let mut handle = Box::new(TestS3FifoHandle::new()); + let mut handle = Box::::default(); handle.init(i, i, 1, S3FifoContext); NonNull::new_unchecked(Box::into_raw(handle)) }) diff --git a/foyer-memory/src/generic.rs b/foyer-memory/src/generic.rs index d30192cb..0c9dcc8c 100644 --- a/foyer-memory/src/generic.rs +++ b/foyer-memory/src/generic.rs @@ -15,8 +15,7 @@ use std::{ borrow::Borrow, future::Future, - hash::BuildHasher, - hash::Hash, + hash::{BuildHasher, Hash}, ops::Deref, ptr::NonNull, sync::{ @@ -38,7 +37,7 @@ use tokio::{sync::oneshot, task::JoinHandle}; use crate::{ eviction::Eviction, - handle::{Handle, KeyedHandle}, + handle::{Handle, HandleExt, KeyedHandle}, indexer::Indexer, listener::CacheEventListener, metrics::Metrics, @@ -114,15 +113,15 @@ where hash: u64, key: K, value: V, - charge: usize, + weight: usize, context: ::Context, last_reference_entries: &mut Vec<(K, V, ::Context, usize)>, ) -> NonNull { let mut handle = self.state.object_pool.acquire(); - handle.init(hash, (key, value), charge, context); + handle.init(hash, (key, value), weight, context); let mut ptr = unsafe { NonNull::new_unchecked(Box::into_raw(handle)) }; - self.evict(charge, last_reference_entries); + self.evict(weight, last_reference_entries); debug_assert!(!ptr.as_ref().base().is_in_indexer()); if let Some(old) = self.indexer.insert(ptr) { @@ -145,7 +144,7 @@ where debug_assert!(ptr.as_ref().base().is_in_indexer()); debug_assert!(ptr.as_ref().base().is_in_indexer()); - self.usage.fetch_add(charge, Ordering::Relaxed); + self.usage.fetch_add(weight, Ordering::Relaxed); ptr.as_mut().base_mut().inc_refs(); ptr @@ -261,11 +260,11 @@ where unsafe fn evict( &mut self, - charge: usize, + weight: usize, last_reference_entries: &mut Vec<(K, V, ::Context, usize)>, ) { // TODO(MrCroxx): Use `let_chains` here after it is stable. - while self.usage.load(Ordering::Relaxed) + charge > self.capacity { + while self.usage.load(Ordering::Relaxed) + weight > self.capacity { let evicted = match self.eviction.pop() { Some(evicted) => evicted, None => break, @@ -314,7 +313,7 @@ where // the eviction container. if handle.base().is_in_indexer() { // The usage is higher than the capacity means most handles are held externally, - // the cache shard cannot release enough charges for the new inserted entries. + // the cache shard cannot release enough weight for the new inserted entries. // In this case, the reinsertion should be given up. if reinsert && self.usage.load(Ordering::Relaxed) <= self.capacity { let was_in_eviction = handle.base().is_in_eviction(); @@ -341,13 +340,13 @@ where self.state.metrics.release.fetch_add(1, Ordering::Relaxed); - self.usage.fetch_sub(handle.base().charge(), Ordering::Relaxed); - let ((key, value), context, charge) = handle.base_mut().take(); + self.usage.fetch_sub(handle.base().weight(), Ordering::Relaxed); + let ((key, value), context, weight) = handle.base_mut().take(); let handle = Box::from_raw(ptr.as_ptr()); self.state.object_pool.release(handle); - Some((key, value, context, charge)) + Some((key, value, context, weight)) } } @@ -482,9 +481,7 @@ where let usages = (0..config.shards).map(|_| Arc::new(AtomicUsize::new(0))).collect_vec(); let context = Arc::new(CacheSharedState { metrics: Metrics::default(), - object_pool: ObjectPool::new_with_create(config.object_pool_capacity, || { - Box::new(::new()) - }), + object_pool: ObjectPool::new_with_create(config.object_pool_capacity, Box::default), listener: config.event_listener, }); @@ -545,8 +542,8 @@ where } // Do not deallocate data within the lock section. - for (key, value, context, charges) in to_deallocate { - self.context.listener.on_release(key, value, context.into(), charges) + for (key, value, context, weight) in to_deallocate { + self.context.listener.on_release(key, value, context.into(), weight) } entry @@ -687,8 +684,8 @@ where }; // Do not deallocate data within the lock section. - if let Some((key, value, context, charges)) = entry { - self.context.listener.on_release(key, value, context.into(), charges); + if let Some((key, value, context, weight)) = entry { + self.context.listener.on_release(key, value, context.into(), weight); } } } @@ -791,8 +788,8 @@ where unsafe { self.ptr.as_ref().base().context() } } - pub fn charge(&self) -> usize { - unsafe { self.ptr.as_ref().base().charge() } + pub fn weight(&self) -> usize { + unsafe { self.ptr.as_ref().base().weight() } } pub fn refs(&self) -> usize { diff --git a/foyer-memory/src/handle.rs b/foyer-memory/src/handle.rs index bd7d62b9..21c06e37 100644 --- a/foyer-memory/src/handle.rs +++ b/foyer-memory/src/handle.rs @@ -26,17 +26,21 @@ bitflags! { } } -pub trait Handle: Send + Sync + 'static { +pub trait Handle: Send + Sync + 'static + Default { type Data; type Context: Context; - fn new() -> Self; - fn init(&mut self, hash: u64, data: Self::Data, charge: usize, context: Self::Context); - fn base(&self) -> &BaseHandle; fn base_mut(&mut self) -> &mut BaseHandle; } +pub trait HandleExt: Handle { + fn init(&mut self, hash: u64, data: Self::Data, weight: usize, context: Self::Context) { + self.base_mut().init(hash, data, weight, context); + } +} +impl HandleExt for H {} + pub trait KeyedHandle: Handle { type Key; @@ -62,8 +66,8 @@ pub struct BaseHandle { entry: Option<(T, C)>, /// key hash hash: u64, - /// entry charge - charge: usize, + /// entry weight + weight: usize, /// external reference count refs: usize, /// flags that used by the general cache abstraction @@ -83,7 +87,7 @@ impl BaseHandle { Self { entry: None, hash: 0, - charge: 0, + weight: 0, refs: 0, flags: BaseHandleFlags::empty(), } @@ -91,11 +95,12 @@ impl BaseHandle { /// Init handle with args. #[inline(always)] - pub fn init(&mut self, hash: u64, data: T, charge: usize, context: C) { + pub fn init(&mut self, hash: u64, data: T, weight: usize, context: C) { debug_assert!(self.entry.is_none()); + assert_ne!(weight, 0); self.hash = hash; self.entry = Some((data, context)); - self.charge = charge; + self.weight = weight; self.refs = 0; self.flags = BaseHandleFlags::empty(); } @@ -107,7 +112,7 @@ impl BaseHandle { unsafe { self.entry .take() - .map(|(data, context)| (data, context, self.charge)) + .map(|(data, context)| (data, context, self.weight)) .unwrap_unchecked() } } @@ -150,10 +155,10 @@ impl BaseHandle { unsafe { self.entry.as_ref().map(|entry| &entry.1).unwrap_unchecked() } } - /// Get the charge of the handle. + /// Get the weight of the handle. #[inline(always)] - pub fn charge(&self) -> usize { - self.charge + pub fn weight(&self) -> usize { + self.weight } /// Increase the external reference count of the handle, returns the new reference count. diff --git a/foyer-memory/src/listener.rs b/foyer-memory/src/listener.rs index f22d4f3f..3a845b5f 100644 --- a/foyer-memory/src/listener.rs +++ b/foyer-memory/src/listener.rs @@ -26,7 +26,7 @@ where /// The function is called when an entry is released by the cache and all external users. /// /// The arguments includes the key and value with ownership. - fn on_release(&self, key: K, value: V, context: CacheContext, charges: usize); + fn on_release(&self, key: K, value: V, context: CacheContext, weight: usize); } pub struct DefaultCacheEventListener(PhantomData<(K, V)>) @@ -49,5 +49,5 @@ where K: Key, V: Value, { - fn on_release(&self, _key: K, _value: V, _context: CacheContext, _charges: usize) {} + fn on_release(&self, _key: K, _value: V, _context: CacheContext, _weight: usize) {} }