From ed8d539d144122915b3172c9811218f805384623 Mon Sep 17 00:00:00 2001 From: Tatsuya Kawano Date: Tue, 1 Feb 2022 19:34:06 +0800 Subject: [PATCH] Replace some `std::sync::Arc` with `triomphe::Arc` to reduce memory utilization - Replace `Arc` for `Arc`, `Arc` and `Arc`. - Add `triomphe` to the dependencies. Relates to #72. --- .vscode/settings.json | 1 + Cargo.toml | 1 + src/future/value_initializer.rs | 9 ++++---- src/sync.rs | 31 +++++++++++++------------- src/sync/base_cache.rs | 39 +++++++++++++++++---------------- src/sync/deques.rs | 22 +++++++++---------- src/sync/invalidator.rs | 12 +++++----- src/sync/value_initializer.rs | 9 ++++---- 8 files changed, 65 insertions(+), 59 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ec6e3f23..4d0da6b0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,6 +41,7 @@ "Tatsuya", "thiserror", "toolchain", + "triomphe", "trybuild", "Uninit", "unsync", diff --git a/Cargo.toml b/Cargo.toml index c21904a6..c63a2dd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ quanta = "0.9.3" scheduled-thread-pool = "0.2" smallvec = "1.6" thiserror = "1.0" +triomphe = "0.1" uuid = { version = "0.8", features = ["v4"] } # Optional dependencies diff --git a/src/future/value_initializer.rs b/src/future/value_initializer.rs index 2fbff790..53bff8fd 100644 --- a/src/future/value_initializer.rs +++ b/src/future/value_initializer.rs @@ -5,6 +5,7 @@ use std::{ hash::{BuildHasher, Hash}, sync::Arc, }; +use triomphe::Arc as TrioArc; type ErrorObject = Arc; @@ -23,7 +24,7 @@ enum WaiterValue { EnclosingFutureAborted, } -type Waiter = Arc>>; +type Waiter = TrioArc>>; struct WaiterGuard<'a, K, V, S> // NOTE: We usually do not attach trait bounds to here at the struct definition, but @@ -172,7 +173,7 @@ where let mut retries = 0; loop { - let waiter = Arc::new(RwLock::new(WaiterValue::Computing)); + let waiter = TrioArc::new(RwLock::new(WaiterValue::Computing)); let mut lock = waiter.write().await; match self.try_insert_waiter(key, type_id, &waiter) { @@ -246,10 +247,10 @@ where waiter: &Waiter, ) -> Option> { let key = Arc::clone(key); - let waiter = Arc::clone(waiter); + let waiter = TrioArc::clone(waiter); self.waiters - .insert_with_or_modify((key, type_id), || waiter, |_, w| Arc::clone(w)) + .insert_with_or_modify((key, type_id), || waiter, |_, w| TrioArc::clone(w)) } } diff --git a/src/sync.rs b/src/sync.rs index 35fe8dcd..cb13dfd9 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -4,6 +4,7 @@ use crate::common::{deque::DeqNode, time::Instant}; use parking_lot::Mutex; use std::{ptr::NonNull, sync::Arc}; +use triomphe::Arc as TrioArc; pub(crate) mod base_cache; mod builder; @@ -68,14 +69,14 @@ impl Clone for KeyHash { pub(crate) struct KeyDate { key: Arc, - entry_info: Arc, + entry_info: TrioArc, } impl KeyDate { - pub(crate) fn new(key: Arc, entry_info: &Arc) -> Self { + pub(crate) fn new(key: Arc, entry_info: &TrioArc) -> Self { Self { key, - entry_info: Arc::clone(entry_info), + entry_info: TrioArc::clone(entry_info), } } @@ -91,15 +92,15 @@ impl KeyDate { pub(crate) struct KeyHashDate { key: Arc, hash: u64, - entry_info: Arc, + entry_info: TrioArc, } impl KeyHashDate { - pub(crate) fn new(kh: KeyHash, entry_info: &Arc) -> Self { + pub(crate) fn new(kh: KeyHash, entry_info: &TrioArc) -> Self { Self { key: kh.key, hash: kh.hash, - entry_info: Arc::clone(entry_info), + entry_info: TrioArc::clone(entry_info), } } @@ -114,11 +115,11 @@ impl KeyHashDate { pub(crate) struct KvEntry { pub(crate) key: Arc, - pub(crate) entry: Arc>, + pub(crate) entry: TrioArc>, } impl KvEntry { - pub(crate) fn new(key: Arc, entry: Arc>) -> Self { + pub(crate) fn new(key: Arc, entry: TrioArc>) -> Self { Self { key, entry } } } @@ -183,12 +184,12 @@ unsafe impl Send for DeqNodes {} pub(crate) struct ValueEntry { pub(crate) value: V, - info: Arc, + info: TrioArc, nodes: Mutex>, } impl ValueEntry { - fn new(value: V, entry_info: Arc) -> Self { + fn new(value: V, entry_info: TrioArc) -> Self { Self { value, info: entry_info, @@ -199,7 +200,7 @@ impl ValueEntry { } } - fn new_from(value: V, entry_info: Arc, other: &Self) -> Self { + fn new_from(value: V, entry_info: TrioArc, other: &Self) -> Self { let nodes = { let other_nodes = other.nodes.lock(); DeqNodes { @@ -218,7 +219,7 @@ impl ValueEntry { } } - pub(crate) fn entry_info(&self) -> &Arc { + pub(crate) fn entry_info(&self) -> &TrioArc { &self.info } @@ -266,7 +267,7 @@ impl ValueEntry { } } -impl AccessTime for Arc> { +impl AccessTime for TrioArc> { #[inline] fn last_accessed(&self) -> Option { self.info.last_accessed() @@ -290,14 +291,14 @@ impl AccessTime for Arc> { pub(crate) enum ReadOp { // u64 is the hash of the key. - Hit(u64, Arc>, Instant), + Hit(u64, TrioArc>, Instant), Miss(u64), } pub(crate) enum WriteOp { Upsert { key_hash: KeyHash, - value_entry: Arc>, + value_entry: TrioArc>, old_weight: u32, new_weight: u32, }, diff --git a/src/sync/base_cache.rs b/src/sync/base_cache.rs index 22720337..5b31a7d4 100644 --- a/src/sync/base_cache.rs +++ b/src/sync/base_cache.rs @@ -32,6 +32,7 @@ use std::{ }, time::Duration, }; +use triomphe::Arc as TrioArc; pub(crate) const MAX_SYNC_REPEATS: usize = 4; @@ -271,7 +272,7 @@ where cnt, WriteOp::Upsert { key_hash: KeyHash::new(Arc::clone(&key), hash), - value_entry: Arc::clone(&entry), + value_entry: TrioArc::clone(&entry), old_weight: 0, new_weight: weight, }, @@ -290,10 +291,10 @@ where let cnt = op_cnt2.fetch_add(1, Ordering::Relaxed); op2 = Some(( cnt, - Arc::clone(old_entry), + TrioArc::clone(old_entry), WriteOp::Upsert { key_hash: KeyHash::new(Arc::clone(&key), hash), - value_entry: Arc::clone(&entry), + value_entry: TrioArc::clone(&entry), old_weight, new_weight: weight, }, @@ -321,9 +322,9 @@ where } #[inline] - fn new_value_entry(&self, value: V, policy_weight: u32) -> Arc> { - let info = Arc::new(EntryInfo::new(policy_weight)); - Arc::new(ValueEntry::new(value, info)) + fn new_value_entry(&self, value: V, policy_weight: u32) -> TrioArc> { + let info = TrioArc::new(EntryInfo::new(policy_weight)); + TrioArc::new(ValueEntry::new(value, info)) } #[inline] @@ -332,10 +333,10 @@ where value: V, policy_weight: u32, other: &ValueEntry, - ) -> Arc> { - let info = Arc::clone(other.entry_info()); + ) -> TrioArc> { + let info = TrioArc::clone(other.entry_info()); info.set_policy_weight(policy_weight); - Arc::new(ValueEntry::new_from(value, info, other)) + TrioArc::new(ValueEntry::new_from(value, info, other)) } #[inline] @@ -457,9 +458,9 @@ enum AdmissionResult { }, } -type CacheStore = crate::cht::SegmentedHashMap, Arc>, S>; +type CacheStore = crate::cht::SegmentedHashMap, TrioArc>, S>; -type CacheEntry = (Arc, Arc>); +type CacheEntry = (Arc, TrioArc>); pub(crate) struct Inner { max_capacity: Option, @@ -636,7 +637,7 @@ where } #[inline] - fn is_invalidated_entry(&self, key: &Arc, entry: &Arc>) -> bool { + fn is_invalidated_entry(&self, key: &Arc, entry: &TrioArc>) -> bool { if self.invalidator_enabled { if let Some(inv) = &*self.invalidator.read() { return inv.apply_predicates(key, entry); @@ -671,13 +672,13 @@ where K: Hash + Eq, S: BuildHasher, { - fn get_value_entry(&self, key: &Arc) -> Option>> { + fn get_value_entry(&self, key: &Arc) -> Option>> { self.cache.get(key) } - fn remove_key_value_if(&self, key: &Arc, condition: F) -> Option>> + fn remove_key_value_if(&self, key: &Arc, condition: F) -> Option>> where - F: FnMut(&Arc, &Arc>) -> bool, + F: FnMut(&Arc, &TrioArc>) -> bool, { self.cache.remove_if(key, condition) } @@ -875,7 +876,7 @@ where fn handle_upsert( &self, kh: KeyHash, - entry: Arc>, + entry: TrioArc>, old_weight: u32, new_weight: u32, timestamp: Instant, @@ -1035,7 +1036,7 @@ where fn handle_admit( &self, kh: KeyHash, - entry: &Arc>, + entry: &TrioArc>, policy_weight: u32, deqs: &mut Deques, counters: &mut EvictionCounters, @@ -1055,7 +1056,7 @@ where fn handle_remove( deqs: &mut Deques, - entry: Arc>, + entry: TrioArc>, counters: &mut EvictionCounters, ) { if entry.is_admitted() { @@ -1071,7 +1072,7 @@ where ao_deq_name: &str, ao_deq: &mut Deque>, wo_deq: &mut Deque>, - entry: Arc>, + entry: TrioArc>, counters: &mut EvictionCounters, ) { if entry.is_admitted() { diff --git a/src/sync/deques.rs b/src/sync/deques.rs index 68f400d7..3c8a6749 100644 --- a/src/sync/deques.rs +++ b/src/sync/deques.rs @@ -1,8 +1,8 @@ use super::{KeyDate, KeyHashDate, ValueEntry}; use crate::common::deque::{CacheRegion, DeqNode, Deque}; -use std::{ptr::NonNull, sync::Arc}; - +use std::ptr::NonNull; +use triomphe::Arc as TrioArc; pub(crate) struct Deques { pub(crate) window: Deque>, // Not used yet. pub(crate) probation: Deque>, @@ -34,7 +34,7 @@ impl Deques { &mut self, region: CacheRegion, khd: KeyHashDate, - entry: &Arc>, + entry: &TrioArc>, ) { use CacheRegion::*; let node = Box::new(DeqNode::new(region, khd)); @@ -47,13 +47,13 @@ impl Deques { entry.set_access_order_q_node(Some(node)); } - pub(crate) fn push_back_wo(&mut self, kd: KeyDate, entry: &Arc>) { + pub(crate) fn push_back_wo(&mut self, kd: KeyDate, entry: &TrioArc>) { let node = Box::new(DeqNode::new(CacheRegion::WriteOrder, kd)); let node = self.write_order.push_back(node); entry.set_write_order_q_node(Some(node)); } - pub(crate) fn move_to_back_ao(&mut self, entry: &Arc>) { + pub(crate) fn move_to_back_ao(&mut self, entry: &TrioArc>) { use CacheRegion::*; if let Some(node) = entry.access_order_q_node() { let p = unsafe { node.as_ref() }; @@ -73,7 +73,7 @@ impl Deques { pub(crate) fn move_to_back_ao_in_deque( deq_name: &str, deq: &mut Deque>, - entry: &Arc>, + entry: &TrioArc>, ) { if let Some(node) = entry.access_order_q_node() { let p = unsafe { node.as_ref() }; @@ -90,7 +90,7 @@ impl Deques { } } - pub(crate) fn move_to_back_wo(&mut self, entry: &Arc>) { + pub(crate) fn move_to_back_wo(&mut self, entry: &TrioArc>) { use CacheRegion::*; if let Some(node) = entry.write_order_q_node() { let p = unsafe { node.as_ref() }; @@ -103,7 +103,7 @@ impl Deques { pub(crate) fn move_to_back_wo_in_deque( deq: &mut Deque>, - entry: &Arc>, + entry: &TrioArc>, ) { if let Some(node) = entry.write_order_q_node() { let p = unsafe { node.as_ref() }; @@ -120,7 +120,7 @@ impl Deques { } } - pub(crate) fn unlink_ao(&mut self, entry: &Arc>) { + pub(crate) fn unlink_ao(&mut self, entry: &TrioArc>) { if let Some(node) = entry.take_access_order_q_node() { self.unlink_node_ao(node); } @@ -129,14 +129,14 @@ impl Deques { pub(crate) fn unlink_ao_from_deque( deq_name: &str, deq: &mut Deque>, - entry: &Arc>, + entry: &TrioArc>, ) { if let Some(node) = entry.take_access_order_q_node() { unsafe { Self::unlink_node_ao_from_deque(deq_name, deq, node) }; } } - pub(crate) fn unlink_wo(deq: &mut Deque>, entry: &Arc>) { + pub(crate) fn unlink_wo(deq: &mut Deque>, entry: &TrioArc>) { if let Some(node) = entry.take_write_order_q_node() { Self::unlink_node_wo(deq, node); } diff --git a/src/sync/invalidator.rs b/src/sync/invalidator.rs index 861a1c3e..22f74f8e 100644 --- a/src/sync/invalidator.rs +++ b/src/sync/invalidator.rs @@ -8,7 +8,6 @@ use crate::{ }, PredicateError, }; - use super::{base_cache::Inner, AccessTime, KvEntry, PredicateId, PredicateIdStr, ValueEntry}; use parking_lot::{Mutex, RwLock}; @@ -22,16 +21,17 @@ use std::{ }, time::Duration, }; +use triomphe::Arc as TrioArc; use uuid::Uuid; pub(crate) type PredicateFun = Arc bool + Send + Sync + 'static>; pub(crate) trait GetOrRemoveEntry { - fn get_value_entry(&self, key: &Arc) -> Option>>; + fn get_value_entry(&self, key: &Arc) -> Option>>; - fn remove_key_value_if(&self, key: &Arc, condition: F) -> Option>> + fn remove_key_value_if(&self, key: &Arc, condition: F) -> Option>> where - F: FnMut(&Arc, &Arc>) -> bool; + F: FnMut(&Arc, &TrioArc>) -> bool; } pub(crate) struct KeyDateLite { @@ -161,7 +161,7 @@ impl Invalidator { // This method will be called by the get method of Cache. #[inline] - pub(crate) fn apply_predicates(&self, key: &Arc, entry: &Arc>) -> bool { + pub(crate) fn apply_predicates(&self, key: &Arc, entry: &TrioArc>) -> bool { if self.is_empty() { false } else if let Some(ts) = entry.last_modified() { @@ -434,7 +434,7 @@ where false } - fn invalidate(cache: &Arc, key: &Arc, ts: Instant) -> Option>> + fn invalidate(cache: &Arc, key: &Arc, ts: Instant) -> Option>> where Arc: GetOrRemoveEntry, { diff --git a/src/sync/value_initializer.rs b/src/sync/value_initializer.rs index 2e7ea9fe..bc725b27 100644 --- a/src/sync/value_initializer.rs +++ b/src/sync/value_initializer.rs @@ -4,10 +4,11 @@ use std::{ hash::{BuildHasher, Hash}, sync::Arc, }; +use triomphe::Arc as TrioArc; type ErrorObject = Arc; type WaiterValue = Option>; -type Waiter = Arc>>; +type Waiter = TrioArc>>; pub(crate) enum InitResult { Initialized(V), @@ -97,7 +98,7 @@ where let mut retries = 0; loop { - let waiter = Arc::new(RwLock::new(None)); + let waiter = TrioArc::new(RwLock::new(None)); let mut lock = waiter.write(); match self.try_insert_waiter(key, type_id, &waiter) { @@ -157,9 +158,9 @@ where waiter: &Waiter, ) -> Option> { let key = Arc::clone(key); - let waiter = Arc::clone(waiter); + let waiter = TrioArc::clone(waiter); self.waiters - .insert_with_or_modify((key, type_id), || waiter, |_, w| Arc::clone(w)) + .insert_with_or_modify((key, type_id), || waiter, |_, w| TrioArc::clone(w)) } }