Skip to content

Commit

Permalink
Replace some std::sync::Arc with triomphe::Arc to reduce memory u…
Browse files Browse the repository at this point in the history
…tilization

- Replace `Arc` for `Arc<ValueEntry>`, `Arc<EntryInfo>` and `Arc<value_initializer::Waiter>`.
- Add `triomphe` to the dependencies.

Relates to #72.
  • Loading branch information
tatsuya6502 committed Feb 1, 2022
1 parent 09b3f31 commit ed8d539
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 59 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"Tatsuya",
"thiserror",
"toolchain",
"triomphe",
"trybuild",
"Uninit",
"unsync",
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions src/future/value_initializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{
hash::{BuildHasher, Hash},
sync::Arc,
};
use triomphe::Arc as TrioArc;

type ErrorObject = Arc<dyn Any + Send + Sync + 'static>;

Expand All @@ -23,7 +24,7 @@ enum WaiterValue<V> {
EnclosingFutureAborted,
}

type Waiter<V> = Arc<RwLock<WaiterValue<V>>>;
type Waiter<V> = TrioArc<RwLock<WaiterValue<V>>>;

struct WaiterGuard<'a, K, V, S>
// NOTE: We usually do not attach trait bounds to here at the struct definition, but
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -246,10 +247,10 @@ where
waiter: &Waiter<V>,
) -> Option<Waiter<V>> {
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))
}
}

Expand Down
31 changes: 16 additions & 15 deletions src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -68,14 +69,14 @@ impl<K> Clone for KeyHash<K> {

pub(crate) struct KeyDate<K> {
key: Arc<K>,
entry_info: Arc<EntryInfo>,
entry_info: TrioArc<EntryInfo>,
}

impl<K> KeyDate<K> {
pub(crate) fn new(key: Arc<K>, entry_info: &Arc<EntryInfo>) -> Self {
pub(crate) fn new(key: Arc<K>, entry_info: &TrioArc<EntryInfo>) -> Self {
Self {
key,
entry_info: Arc::clone(entry_info),
entry_info: TrioArc::clone(entry_info),
}
}

Expand All @@ -91,15 +92,15 @@ impl<K> KeyDate<K> {
pub(crate) struct KeyHashDate<K> {
key: Arc<K>,
hash: u64,
entry_info: Arc<EntryInfo>,
entry_info: TrioArc<EntryInfo>,
}

impl<K> KeyHashDate<K> {
pub(crate) fn new(kh: KeyHash<K>, entry_info: &Arc<EntryInfo>) -> Self {
pub(crate) fn new(kh: KeyHash<K>, entry_info: &TrioArc<EntryInfo>) -> Self {
Self {
key: kh.key,
hash: kh.hash,
entry_info: Arc::clone(entry_info),
entry_info: TrioArc::clone(entry_info),
}
}

Expand All @@ -114,11 +115,11 @@ impl<K> KeyHashDate<K> {

pub(crate) struct KvEntry<K, V> {
pub(crate) key: Arc<K>,
pub(crate) entry: Arc<ValueEntry<K, V>>,
pub(crate) entry: TrioArc<ValueEntry<K, V>>,
}

impl<K, V> KvEntry<K, V> {
pub(crate) fn new(key: Arc<K>, entry: Arc<ValueEntry<K, V>>) -> Self {
pub(crate) fn new(key: Arc<K>, entry: TrioArc<ValueEntry<K, V>>) -> Self {
Self { key, entry }
}
}
Expand Down Expand Up @@ -183,12 +184,12 @@ unsafe impl<K> Send for DeqNodes<K> {}

pub(crate) struct ValueEntry<K, V> {
pub(crate) value: V,
info: Arc<EntryInfo>,
info: TrioArc<EntryInfo>,
nodes: Mutex<DeqNodes<K>>,
}

impl<K, V> ValueEntry<K, V> {
fn new(value: V, entry_info: Arc<EntryInfo>) -> Self {
fn new(value: V, entry_info: TrioArc<EntryInfo>) -> Self {
Self {
value,
info: entry_info,
Expand All @@ -199,7 +200,7 @@ impl<K, V> ValueEntry<K, V> {
}
}

fn new_from(value: V, entry_info: Arc<EntryInfo>, other: &Self) -> Self {
fn new_from(value: V, entry_info: TrioArc<EntryInfo>, other: &Self) -> Self {
let nodes = {
let other_nodes = other.nodes.lock();
DeqNodes {
Expand All @@ -218,7 +219,7 @@ impl<K, V> ValueEntry<K, V> {
}
}

pub(crate) fn entry_info(&self) -> &Arc<EntryInfo> {
pub(crate) fn entry_info(&self) -> &TrioArc<EntryInfo> {
&self.info
}

Expand Down Expand Up @@ -266,7 +267,7 @@ impl<K, V> ValueEntry<K, V> {
}
}

impl<K, V> AccessTime for Arc<ValueEntry<K, V>> {
impl<K, V> AccessTime for TrioArc<ValueEntry<K, V>> {
#[inline]
fn last_accessed(&self) -> Option<Instant> {
self.info.last_accessed()
Expand All @@ -290,14 +291,14 @@ impl<K, V> AccessTime for Arc<ValueEntry<K, V>> {

pub(crate) enum ReadOp<K, V> {
// u64 is the hash of the key.
Hit(u64, Arc<ValueEntry<K, V>>, Instant),
Hit(u64, TrioArc<ValueEntry<K, V>>, Instant),
Miss(u64),
}

pub(crate) enum WriteOp<K, V> {
Upsert {
key_hash: KeyHash<K>,
value_entry: Arc<ValueEntry<K, V>>,
value_entry: TrioArc<ValueEntry<K, V>>,
old_weight: u32,
new_weight: u32,
},
Expand Down
39 changes: 20 additions & 19 deletions src/sync/base_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::{
},
time::Duration,
};
use triomphe::Arc as TrioArc;

pub(crate) const MAX_SYNC_REPEATS: usize = 4;

Expand Down Expand Up @@ -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,
},
Expand All @@ -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,
},
Expand Down Expand Up @@ -321,9 +322,9 @@ where
}

#[inline]
fn new_value_entry(&self, value: V, policy_weight: u32) -> Arc<ValueEntry<K, V>> {
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<ValueEntry<K, V>> {
let info = TrioArc::new(EntryInfo::new(policy_weight));
TrioArc::new(ValueEntry::new(value, info))
}

#[inline]
Expand All @@ -332,10 +333,10 @@ where
value: V,
policy_weight: u32,
other: &ValueEntry<K, V>,
) -> Arc<ValueEntry<K, V>> {
let info = Arc::clone(other.entry_info());
) -> TrioArc<ValueEntry<K, V>> {
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]
Expand Down Expand Up @@ -457,9 +458,9 @@ enum AdmissionResult<K> {
},
}

type CacheStore<K, V, S> = crate::cht::SegmentedHashMap<Arc<K>, Arc<ValueEntry<K, V>>, S>;
type CacheStore<K, V, S> = crate::cht::SegmentedHashMap<Arc<K>, TrioArc<ValueEntry<K, V>>, S>;

type CacheEntry<K, V> = (Arc<K>, Arc<ValueEntry<K, V>>);
type CacheEntry<K, V> = (Arc<K>, TrioArc<ValueEntry<K, V>>);

pub(crate) struct Inner<K, V, S> {
max_capacity: Option<u64>,
Expand Down Expand Up @@ -636,7 +637,7 @@ where
}

#[inline]
fn is_invalidated_entry(&self, key: &Arc<K>, entry: &Arc<ValueEntry<K, V>>) -> bool {
fn is_invalidated_entry(&self, key: &Arc<K>, entry: &TrioArc<ValueEntry<K, V>>) -> bool {
if self.invalidator_enabled {
if let Some(inv) = &*self.invalidator.read() {
return inv.apply_predicates(key, entry);
Expand Down Expand Up @@ -671,13 +672,13 @@ where
K: Hash + Eq,
S: BuildHasher,
{
fn get_value_entry(&self, key: &Arc<K>) -> Option<Arc<ValueEntry<K, V>>> {
fn get_value_entry(&self, key: &Arc<K>) -> Option<TrioArc<ValueEntry<K, V>>> {
self.cache.get(key)
}

fn remove_key_value_if<F>(&self, key: &Arc<K>, condition: F) -> Option<Arc<ValueEntry<K, V>>>
fn remove_key_value_if<F>(&self, key: &Arc<K>, condition: F) -> Option<TrioArc<ValueEntry<K, V>>>
where
F: FnMut(&Arc<K>, &Arc<ValueEntry<K, V>>) -> bool,
F: FnMut(&Arc<K>, &TrioArc<ValueEntry<K, V>>) -> bool,
{
self.cache.remove_if(key, condition)
}
Expand Down Expand Up @@ -875,7 +876,7 @@ where
fn handle_upsert(
&self,
kh: KeyHash<K>,
entry: Arc<ValueEntry<K, V>>,
entry: TrioArc<ValueEntry<K, V>>,
old_weight: u32,
new_weight: u32,
timestamp: Instant,
Expand Down Expand Up @@ -1035,7 +1036,7 @@ where
fn handle_admit(
&self,
kh: KeyHash<K>,
entry: &Arc<ValueEntry<K, V>>,
entry: &TrioArc<ValueEntry<K, V>>,
policy_weight: u32,
deqs: &mut Deques<K>,
counters: &mut EvictionCounters,
Expand All @@ -1055,7 +1056,7 @@ where

fn handle_remove(
deqs: &mut Deques<K>,
entry: Arc<ValueEntry<K, V>>,
entry: TrioArc<ValueEntry<K, V>>,
counters: &mut EvictionCounters,
) {
if entry.is_admitted() {
Expand All @@ -1071,7 +1072,7 @@ where
ao_deq_name: &str,
ao_deq: &mut Deque<KeyHashDate<K>>,
wo_deq: &mut Deque<KeyDate<K>>,
entry: Arc<ValueEntry<K, V>>,
entry: TrioArc<ValueEntry<K, V>>,
counters: &mut EvictionCounters,
) {
if entry.is_admitted() {
Expand Down
22 changes: 11 additions & 11 deletions src/sync/deques.rs
Original file line number Diff line number Diff line change
@@ -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<K> {
pub(crate) window: Deque<KeyHashDate<K>>, // Not used yet.
pub(crate) probation: Deque<KeyHashDate<K>>,
Expand Down Expand Up @@ -34,7 +34,7 @@ impl<K> Deques<K> {
&mut self,
region: CacheRegion,
khd: KeyHashDate<K>,
entry: &Arc<ValueEntry<K, V>>,
entry: &TrioArc<ValueEntry<K, V>>,
) {
use CacheRegion::*;
let node = Box::new(DeqNode::new(region, khd));
Expand All @@ -47,13 +47,13 @@ impl<K> Deques<K> {
entry.set_access_order_q_node(Some(node));
}

pub(crate) fn push_back_wo<V>(&mut self, kd: KeyDate<K>, entry: &Arc<ValueEntry<K, V>>) {
pub(crate) fn push_back_wo<V>(&mut self, kd: KeyDate<K>, entry: &TrioArc<ValueEntry<K, V>>) {
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<V>(&mut self, entry: &Arc<ValueEntry<K, V>>) {
pub(crate) fn move_to_back_ao<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
use CacheRegion::*;
if let Some(node) = entry.access_order_q_node() {
let p = unsafe { node.as_ref() };
Expand All @@ -73,7 +73,7 @@ impl<K> Deques<K> {
pub(crate) fn move_to_back_ao_in_deque<V>(
deq_name: &str,
deq: &mut Deque<KeyHashDate<K>>,
entry: &Arc<ValueEntry<K, V>>,
entry: &TrioArc<ValueEntry<K, V>>,
) {
if let Some(node) = entry.access_order_q_node() {
let p = unsafe { node.as_ref() };
Expand All @@ -90,7 +90,7 @@ impl<K> Deques<K> {
}
}

pub(crate) fn move_to_back_wo<V>(&mut self, entry: &Arc<ValueEntry<K, V>>) {
pub(crate) fn move_to_back_wo<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
use CacheRegion::*;
if let Some(node) = entry.write_order_q_node() {
let p = unsafe { node.as_ref() };
Expand All @@ -103,7 +103,7 @@ impl<K> Deques<K> {

pub(crate) fn move_to_back_wo_in_deque<V>(
deq: &mut Deque<KeyDate<K>>,
entry: &Arc<ValueEntry<K, V>>,
entry: &TrioArc<ValueEntry<K, V>>,
) {
if let Some(node) = entry.write_order_q_node() {
let p = unsafe { node.as_ref() };
Expand All @@ -120,7 +120,7 @@ impl<K> Deques<K> {
}
}

pub(crate) fn unlink_ao<V>(&mut self, entry: &Arc<ValueEntry<K, V>>) {
pub(crate) fn unlink_ao<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
if let Some(node) = entry.take_access_order_q_node() {
self.unlink_node_ao(node);
}
Expand All @@ -129,14 +129,14 @@ impl<K> Deques<K> {
pub(crate) fn unlink_ao_from_deque<V>(
deq_name: &str,
deq: &mut Deque<KeyHashDate<K>>,
entry: &Arc<ValueEntry<K, V>>,
entry: &TrioArc<ValueEntry<K, V>>,
) {
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<V>(deq: &mut Deque<KeyDate<K>>, entry: &Arc<ValueEntry<K, V>>) {
pub(crate) fn unlink_wo<V>(deq: &mut Deque<KeyDate<K>>, entry: &TrioArc<ValueEntry<K, V>>) {
if let Some(node) = entry.take_write_order_q_node() {
Self::unlink_node_wo(deq, node);
}
Expand Down
Loading

0 comments on commit ed8d539

Please sign in to comment.