Skip to content

Commit

Permalink
Switch from triomphe::Arc to MiniArc, our own Arc implementation
Browse files Browse the repository at this point in the history
`MiniArc` is like a `std::sync::Arc` but with a few differences:

- No `Weak` references.
- Uses `AtomicU32` instead of `AtomicUsize` for reference counting.
- Much smaller code size by having only the necessary methods for us.
  • Loading branch information
tatsuya6502 committed Sep 14, 2024
1 parent c948f22 commit a651cc6
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 141 deletions.
6 changes: 1 addition & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,13 @@ unstable-debug-counters = ["future", "once_cell"]
crossbeam-channel = "0.5.5"
crossbeam-epoch = "0.9.9"
crossbeam-utils = "0.8"
moka-arc = { git = "https://gitlab.com/moka-labs/moka-gh440-remove-triomphe/moka-arc.git" }
parking_lot = "0.12"
smallvec = "1.8"
tagptr = "0.2"
thiserror = "1.0"
uuid = { version = "1.1", features = ["v4"] }

# Opt-out serde and stable_deref_trait features
# https://github.com/Manishearth/triomphe/pull/5
# 0.1.12 requires Rust 1.76
triomphe = { version = ">=0.1.3, <0.1.12", default-features = false }

# Optional dependencies (enabled by default)
quanta = { version = "0.12.2", optional = true }

Expand Down
50 changes: 25 additions & 25 deletions src/common/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::common::{deque::DeqNode, time::Instant};
use parking_lot::Mutex;
use std::{fmt, ptr::NonNull, sync::Arc};
use tagptr::TagNonNull;
use triomphe::Arc as TrioArc;
use moka_arc::MiniArc;

pub(crate) mod constants;
pub(crate) mod deques;
Expand Down Expand Up @@ -64,13 +64,13 @@ impl<K> Clone for KeyHash<K> {
}

pub(crate) struct KeyHashDate<K> {
entry_info: TrioArc<EntryInfo<K>>,
entry_info: MiniArc<EntryInfo<K>>,
}

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

Expand Down Expand Up @@ -101,11 +101,11 @@ impl<K> KeyHashDate<K> {

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

impl<K, V> KvEntry<K, V> {
pub(crate) fn new(key: Arc<K>, entry: TrioArc<ValueEntry<K, V>>) -> Self {
pub(crate) fn new(key: Arc<K>, entry: MiniArc<ValueEntry<K, V>>) -> Self {
Self { key, entry }
}
}
Expand All @@ -114,7 +114,7 @@ impl<K, V> Clone for KvEntry<K, V> {
fn clone(&self) -> Self {
Self {
key: Arc::clone(&self.key),
entry: TrioArc::clone(&self.entry),
entry: MiniArc::clone(&self.entry),
}
}
}
Expand Down Expand Up @@ -177,33 +177,33 @@ impl<K> DeqNodes<K> {

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

impl<K, V> ValueEntry<K, V> {
pub(crate) fn new(value: V, entry_info: TrioArc<EntryInfo<K>>) -> Self {
pub(crate) fn new(value: V, entry_info: MiniArc<EntryInfo<K>>) -> Self {
#[cfg(feature = "unstable-debug-counters")]
self::debug_counters::InternalGlobalDebugCounters::value_entry_created();

Self {
value,
info: entry_info,
nodes: TrioArc::new(Mutex::new(DeqNodes::default())),
nodes: MiniArc::new(Mutex::new(DeqNodes::default())),
}
}

pub(crate) fn new_from(value: V, entry_info: TrioArc<EntryInfo<K>>, other: &Self) -> Self {
pub(crate) fn new_from(value: V, entry_info: MiniArc<EntryInfo<K>>, other: &Self) -> Self {
#[cfg(feature = "unstable-debug-counters")]
self::debug_counters::InternalGlobalDebugCounters::value_entry_created();
Self {
value,
info: entry_info,
nodes: TrioArc::clone(&other.nodes),
nodes: MiniArc::clone(&other.nodes),
}
}

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

Expand All @@ -224,7 +224,7 @@ impl<K, V> ValueEntry<K, V> {
self.info.policy_weight()
}

pub(crate) fn deq_nodes(&self) -> &TrioArc<Mutex<DeqNodes<K>>> {
pub(crate) fn deq_nodes(&self) -> &MiniArc<Mutex<DeqNodes<K>>> {
&self.nodes
}

Expand Down Expand Up @@ -278,7 +278,7 @@ impl<K, V> Drop for ValueEntry<K, V> {
}
}

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

pub(crate) enum ReadOp<K, V> {
Hit {
value_entry: TrioArc<ValueEntry<K, V>>,
value_entry: MiniArc<ValueEntry<K, V>>,
is_expiry_modified: bool,
},
// u64 is the hash of the key.
Expand All @@ -312,7 +312,7 @@ pub(crate) enum ReadOp<K, V> {
pub(crate) enum WriteOp<K, V> {
Upsert {
key_hash: KeyHash<K>,
value_entry: TrioArc<ValueEntry<K, V>>,
value_entry: MiniArc<ValueEntry<K, V>>,
/// Entry generation after the operation.
entry_gen: u16,
old_weight: u32,
Expand All @@ -324,7 +324,7 @@ pub(crate) enum WriteOp<K, V> {
},
}

/// Cloning a `WriteOp` is safe and cheap because it uses `Arc` and `TrioArc` pointers to
/// Cloning a `WriteOp` is safe and cheap because it uses `Arc` and `MiniArc` pointers to
/// the actual data.
impl<K, V> Clone for WriteOp<K, V> {
fn clone(&self) -> Self {
Expand All @@ -337,7 +337,7 @@ impl<K, V> Clone for WriteOp<K, V> {
new_weight,
} => Self::Upsert {
key_hash: key_hash.clone(),
value_entry: TrioArc::clone(value_entry),
value_entry: MiniArc::clone(value_entry),
entry_gen: *entry_gen,
old_weight: *old_weight,
new_weight: *new_weight,
Expand Down Expand Up @@ -366,13 +366,13 @@ impl<K, V> WriteOp<K, V> {
pub(crate) fn new_upsert(
key: &Arc<K>,
hash: u64,
value_entry: &TrioArc<ValueEntry<K, V>>,
value_entry: &MiniArc<ValueEntry<K, V>>,
entry_generation: u16,
old_weight: u32,
new_weight: u32,
) -> Self {
let key_hash = KeyHash::new(Arc::clone(key), hash);
let value_entry = TrioArc::clone(value_entry);
let value_entry = MiniArc::clone(value_entry);
Self::Upsert {
key_hash,
value_entry,
Expand All @@ -384,15 +384,15 @@ impl<K, V> WriteOp<K, V> {
}

pub(crate) struct OldEntryInfo<K, V> {
pub(crate) entry: TrioArc<ValueEntry<K, V>>,
pub(crate) entry: MiniArc<ValueEntry<K, V>>,
pub(crate) last_accessed: Option<Instant>,
pub(crate) last_modified: Option<Instant>,
}

impl<K, V> OldEntryInfo<K, V> {
pub(crate) fn new(entry: &TrioArc<ValueEntry<K, V>>) -> Self {
pub(crate) fn new(entry: &MiniArc<ValueEntry<K, V>>) -> Self {
Self {
entry: TrioArc::clone(entry),
entry: MiniArc::clone(entry),
last_accessed: entry.last_accessed(),
last_modified: entry.last_modified(),
}
Expand Down
21 changes: 11 additions & 10 deletions src/common/concurrent/deques.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::common::{

use std::ptr::NonNull;
use tagptr::TagNonNull;
use triomphe::Arc as TrioArc;
use moka_arc::MiniArc;

pub(crate) struct Deques<K> {
pub(crate) window: Deque<KeyHashDate<K>>, // Not used yet.
pub(crate) probation: Deque<KeyHashDate<K>>,
Expand Down Expand Up @@ -50,7 +51,7 @@ impl<K> Deques<K> {
&mut self,
region: CacheRegion,
khd: KeyHashDate<K>,
entry: &TrioArc<ValueEntry<K, V>>,
entry: &MiniArc<ValueEntry<K, V>>,
) {
let node = Box::new(DeqNode::new(khd));
let node = match region {
Expand All @@ -66,14 +67,14 @@ impl<K> Deques<K> {
pub(crate) fn push_back_wo<V>(
&mut self,
kd: KeyHashDate<K>,
entry: &TrioArc<ValueEntry<K, V>>,
entry: &MiniArc<ValueEntry<K, V>>,
) {
let node = Box::new(DeqNode::new(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: &TrioArc<ValueEntry<K, V>>) {
pub(crate) fn move_to_back_ao<V>(&mut self, entry: &MiniArc<ValueEntry<K, V>>) {
if let Some(tagged_node) = entry.access_order_q_node() {
let (node, tag) = tagged_node.decompose();
let p = unsafe { node.as_ref() };
Expand All @@ -95,7 +96,7 @@ impl<K> Deques<K> {
pub(crate) fn move_to_back_ao_in_deque<V>(
deq_name: &str,
deq: &mut Deque<KeyHashDate<K>>,
entry: &TrioArc<ValueEntry<K, V>>,
entry: &MiniArc<ValueEntry<K, V>>,
) {
if let Some(tagged_node) = entry.access_order_q_node() {
let (node, tag) = tagged_node.decompose();
Expand All @@ -111,7 +112,7 @@ impl<K> Deques<K> {
}
}

pub(crate) fn move_to_back_wo<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
pub(crate) fn move_to_back_wo<V>(&mut self, entry: &MiniArc<ValueEntry<K, V>>) {
if let Some(node) = entry.write_order_q_node() {
let p = unsafe { node.as_ref() };
if self.write_order.contains(p) {
Expand All @@ -122,7 +123,7 @@ impl<K> Deques<K> {

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

pub(crate) fn unlink_ao<V>(&mut self, entry: &TrioArc<ValueEntry<K, V>>) {
pub(crate) fn unlink_ao<V>(&mut self, entry: &MiniArc<ValueEntry<K, V>>) {
if let Some(node) = entry.take_access_order_q_node() {
self.unlink_node_ao(node);
}
Expand All @@ -141,14 +142,14 @@ impl<K> Deques<K> {
pub(crate) fn unlink_ao_from_deque<V>(
deq_name: &str,
deq: &mut Deque<KeyHashDate<K>>,
entry: &TrioArc<ValueEntry<K, V>>,
entry: &MiniArc<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<KeyHashDate<K>>, entry: &TrioArc<ValueEntry<K, V>>) {
pub(crate) fn unlink_wo<V>(deq: &mut Deque<KeyHashDate<K>>, entry: &MiniArc<ValueEntry<K, V>>) {
if let Some(node) = entry.take_write_order_q_node() {
Self::unlink_node_wo(deq, node);
}
Expand Down
26 changes: 13 additions & 13 deletions src/common/timer_wheel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::{
};

use parking_lot::Mutex;
use triomphe::Arc as TrioArc;
use moka_arc::MiniArc;

const BUCKET_COUNTS: &[u64] = &[
64, // roughly seconds
Expand Down Expand Up @@ -69,16 +69,16 @@ pub(crate) enum TimerNode<K> {
/// The position (level and index) of the timer wheel bucket.
pos: Option<(u8, u8)>,
/// An Arc pointer to the `EntryInfo` of the cache entry (`ValueEntry`).
entry_info: TrioArc<EntryInfo<K>>,
entry_info: MiniArc<EntryInfo<K>>,
/// An Arc pointer to the `DeqNodes` of the cache entry (`ValueEntry`).
deq_nodes: TrioArc<Mutex<DeqNodes<K>>>,
deq_nodes: MiniArc<Mutex<DeqNodes<K>>>,
},
}

impl<K> TimerNode<K> {
fn new(
entry_info: TrioArc<EntryInfo<K>>,
deq_nodes: TrioArc<Mutex<DeqNodes<K>>>,
entry_info: MiniArc<EntryInfo<K>>,
deq_nodes: MiniArc<Mutex<DeqNodes<K>>>,
level: usize,
index: usize,
) -> Self {
Expand Down Expand Up @@ -118,7 +118,7 @@ impl<K> TimerNode<K> {
matches!(self, Self::Sentinel)
}

pub(crate) fn entry_info(&self) -> &TrioArc<EntryInfo<K>> {
pub(crate) fn entry_info(&self) -> &MiniArc<EntryInfo<K>> {
if let Self::Entry { entry_info, .. } = &self {
entry_info
} else {
Expand Down Expand Up @@ -209,8 +209,8 @@ impl<K> TimerWheel<K> {
/// Schedules a timer event for the node.
pub(crate) fn schedule(
&mut self,
entry_info: TrioArc<EntryInfo<K>>,
deq_nodes: TrioArc<Mutex<DeqNodes<K>>>,
entry_info: MiniArc<EntryInfo<K>>,
deq_nodes: MiniArc<Mutex<DeqNodes<K>>>,
) -> Option<NonNull<DeqNode<TimerNode<K>>>> {
debug_assert!(self.is_enabled());

Expand Down Expand Up @@ -397,7 +397,7 @@ pub(crate) enum TimerEvent<K> {
// from one wheel to another in a lower level of the hierarchy. (This variant
// is mainly used for testing)
#[cfg(test)]
Rescheduled(TrioArc<EntryInfo<K>>),
Rescheduled(MiniArc<EntryInfo<K>>),
#[cfg(not(test))]
Rescheduled(()),
/// This timer node (containing a cache entry) has been removed from the timer.
Expand Down Expand Up @@ -517,7 +517,7 @@ impl<'iter, K> Iterator for TimerEventsIter<'iter, K> {
// Get the entry info before rescheduling (mutating) the node to
// avoid Stacked Borrows/Tree Borrows violations on `node_p`.
let entry_info =
TrioArc::clone(unsafe { node_p.as_ref() }.element.entry_info());
MiniArc::clone(unsafe { node_p.as_ref() }.element.entry_info());

match self.timer_wheel.schedule_existing_node(node_p) {
ReschedulingResult::Rescheduled => {
Expand Down Expand Up @@ -564,7 +564,7 @@ mod tests {
time::{CheckedTimeOps, Clock, Instant, Mock},
};

use triomphe::Arc as TrioArc;
use moka_arc::MiniArc;

#[test]
fn test_bucket_indices() {
Expand Down Expand Up @@ -654,10 +654,10 @@ mod tests {
let hash = key as u64;
let key_hash = KeyHash::new(Arc::new(key), hash);
let policy_weight = 0;
let entry_info = TrioArc::new(EntryInfo::new(key_hash, now, policy_weight));
let entry_info = MiniArc::new(EntryInfo::new(key_hash, now, policy_weight));
entry_info.set_expiration_time(Some(now.checked_add(ttl).unwrap()));
let deq_nodes = Default::default();
let timer_node = timer.schedule(entry_info, TrioArc::clone(&deq_nodes));
let timer_node = timer.schedule(entry_info, MiniArc::clone(&deq_nodes));
deq_nodes.lock().set_timer_node(timer_node);
}

Expand Down
Loading

0 comments on commit a651cc6

Please sign in to comment.