From 6c8103915cc0dfe14410064a9e1f3da80f87679f Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Fri, 15 Mar 2024 12:16:01 -0700 Subject: [PATCH] Removed hash maps --- Cargo.lock | 42 +-------- Cargo.toml | 3 +- src/lib.rs | 263 ++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 225 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 637c995..f943b01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,19 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.2" @@ -110,9 +97,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", ] @@ -339,9 +326,9 @@ dependencies = [ [[package]] name = "kempt" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a37a6bdb52eae6acb1efbab069af766555a6d77712380fd48876b83543d3071" +checksum = "35bf4433cfb4933c3e4ad1964ec3dcb183a07154174b96944c20d7f0ae4b1f1b" [[package]] name = "kernel32-sys" @@ -578,7 +565,6 @@ dependencies = [ name = "refuse" version = "0.0.1" dependencies = [ - "ahash", "crossbeam-utils", "flume 0.11.0", "intentional", @@ -1012,23 +998,3 @@ name = "windows_x86_64_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] diff --git a/Cargo.toml b/Cargo.toml index de90bae..76130af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,10 @@ categories = ["memory-management"] keywords = ["gc", "garbage", "collector"] [dependencies] -ahash = "0.8.11" crossbeam-utils = "0.8.19" flume = "0.11.0" intentional = "0.1.1" -kempt = "0.2.3" +kempt = "0.2.4" parking_lot = { version = "0.12.1" } [lints] diff --git a/src/lib.rs b/src/lib.rs index 959863b..83d2e88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,32 @@ #![doc = include_str!("../README.md")] +use core::slice; +use std::alloc::{alloc_zeroed, Layout}; +use std::any::{Any, TypeId}; +use std::cell::{Cell, OnceCell, RefCell, UnsafeCell}; +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; +use std::marker::PhantomData; +use std::mem::ManuallyDrop; +use std::num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, +}; +use std::ops::Deref; +use std::sync::atomic::{ + self, AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, + AtomicU64, AtomicU8, AtomicUsize, Ordering, +}; +use std::sync::{Arc, OnceLock, Weak}; +use std::time::{Duration, Instant}; +use std::{array, thread}; + +use crossbeam_utils::sync::{Parker, Unparker}; +use flume::{Receiver, RecvError, RecvTimeoutError, Sender}; +use intentional::{Assert, Cast}; +use kempt::map::Field; +use kempt::{Map, Set}; +use parking_lot::{Condvar, Mutex, RwLock}; + /// Architecture overview of the underlying design of Refuse. /// /// # Overview @@ -120,28 +147,7 @@ /// implementation invoked. pub mod architecture {} -use core::slice; -use std::alloc::{alloc_zeroed, Layout}; -use std::any::{Any, TypeId}; -use std::cell::{Cell, OnceCell, RefCell, UnsafeCell}; -use std::collections::hash_map; -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::num::NonZeroUsize; -use std::ops::Deref; -use std::sync::atomic::{self, AtomicBool, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering}; -use std::sync::{Arc, OnceLock, Weak}; -use std::time::{Duration, Instant}; -use std::{array, thread}; - -use ahash::AHashMap; -use crossbeam_utils::sync::{Parker, Unparker}; -use flume::{Receiver, RecvError, RecvTimeoutError, Sender}; -use intentional::{Assert, Cast}; -use kempt::Map; -use parking_lot::{Condvar, Mutex, RwLock}; - -#[derive(Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)] struct CollectorThreadId(u32); impl CollectorThreadId { @@ -182,7 +188,7 @@ impl CollectorCommand { } } -type AllThreadBins = Arc>>>; +type AllThreadBins = Arc>>>; struct ThreadBins { alive: bool, @@ -196,7 +202,7 @@ struct CollectorInfo { signalled_collector: AtomicBool, reader_state: ReaderState, all_threads: AllThreadBins, - type_indexes: RwLock>, + type_indexes: RwLock>, } impl CollectorInfo { @@ -235,7 +241,7 @@ struct MarkRequest { struct Collector { shared: Arc, receiver: Receiver, - thread_bins: AHashMap, + thread_bins: Map, active_threads: usize, mark_bits: u8, next_gc: Option, @@ -249,7 +255,7 @@ impl Collector { Self { shared, receiver, - thread_bins: AHashMap::new(), + thread_bins: Map::new(), active_threads: 0, mark_bits: 0, next_gc: None, @@ -390,13 +396,13 @@ impl Collector { } fn acquire_all_locks<'a>( - thread_bins: &'a AHashMap, + thread_bins: &'a Map, start: Instant, average_collection_locking: Duration, pause_failures: u8, collector: &CollectorInfo, parker: &Parker, - ) -> Option> { + ) -> Option> { let force_gc = pause_failures >= 2; let lock_wait = average_collection_locking * u32::from(pause_failures + 1) * 3; let long_lock_deadline = start + lock_wait; @@ -419,7 +425,7 @@ impl Collector { Some( thread_bins .iter() - .map(|(thread_id, bins)| (*thread_id, unsafe { bins.bins.assume_mut() })) + .map(|entry| (*entry.key(), unsafe { entry.value.bins.assume_mut() })) .collect(), ) } @@ -506,7 +512,7 @@ impl Collector { atomic::fence(Ordering::Acquire); let mut threads_to_remove = Vec::new(); - for (thread_id, bins) in all_bins { + for (thread_id, bins) in all_bins.into_iter().map(Field::into_parts) { let mut live_objects = 0_usize; for bin in bins.by_type.write().values_mut() { live_objects = live_objects.saturating_add(bin.sweep(self.mark_bits)); @@ -639,7 +645,7 @@ pub fn collected(wrapped: impl FnOnce() -> R) -> R { loop { let thread_id = CollectorThreadId::unique(); let mut threads = all_threads.write(); - if let hash_map::Entry::Vacant(entry) = threads.entry(thread_id) { + if let kempt::map::Entry::Vacant(entry) = threads.entry(thread_id) { CollectorCommand::NewThread(thread_id, bins.clone()).send(); entry.insert(Arc::downgrade(&bins)); drop(threads); @@ -948,18 +954,48 @@ pub trait SimpleType {} impl NoMapping for T where T: SimpleType {} impl ContainsNoRefs for T where T: SimpleType {} -impl SimpleType for u8 {} -impl SimpleType for u16 {} -impl SimpleType for u32 {} -impl SimpleType for u64 {} -impl SimpleType for u128 {} -impl SimpleType for usize {} -impl SimpleType for i8 {} -impl SimpleType for i16 {} -impl SimpleType for i32 {} -impl SimpleType for i64 {} -impl SimpleType for i128 {} -impl SimpleType for isize {} +macro_rules! impl_simple_type { + ($($ty:ty),+ ,) => { + $(impl SimpleType for $ty {})+ + } +} + +impl_simple_type!( + u8, + u16, + u32, + u64, + u128, + usize, + i8, + i16, + i32, + i64, + i128, + isize, + AtomicU8, + AtomicU16, + AtomicU32, + AtomicU64, + AtomicUsize, + AtomicI8, + AtomicI16, + AtomicI32, + AtomicI64, + AtomicIsize, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize, + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, +); impl Trace for Vec where @@ -976,6 +1012,147 @@ where impl NoMapping for Vec {} +impl Trace for VecDeque +where + T: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = T::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for item in self { + item.trace(tracer); + } + } +} + +impl NoMapping for VecDeque {} + +impl Trace for BinaryHeap +where + T: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = T::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for item in self { + item.trace(tracer); + } + } +} + +impl NoMapping for BinaryHeap {} + +impl Trace for LinkedList +where + T: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = T::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for item in self { + item.trace(tracer); + } + } +} + +impl NoMapping for LinkedList {} + +impl Trace for HashMap +where + K: Trace, + V: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES || V::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for (k, v) in self { + k.trace(tracer); + v.trace(tracer); + } + } +} + +impl NoMapping for HashMap {} + +impl Trace for HashSet +where + K: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for k in self { + k.trace(tracer); + } + } +} + +impl NoMapping for HashSet {} + +impl Trace for BTreeMap +where + K: Trace, + V: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES || V::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for (k, v) in self { + k.trace(tracer); + v.trace(tracer); + } + } +} + +impl NoMapping for BTreeMap {} + +impl Trace for BTreeSet +where + K: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for k in self { + k.trace(tracer); + } + } +} + +impl NoMapping for BTreeSet {} + +impl Trace for Map +where + K: Trace + kempt::Sort, + V: Trace, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES || V::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for field in self { + field.key().trace(tracer); + field.value.trace(tracer); + } + } +} + +impl NoMapping for Map where K: kempt::Sort {} + +impl Trace for Set +where + K: Trace + kempt::Sort, +{ + const MAY_CONTAIN_REFERENCES: bool = K::MAY_CONTAIN_REFERENCES; + + fn trace(&self, tracer: &mut Tracer) { + for k in self { + k.trace(tracer); + } + } +} + +impl NoMapping for Set where K: kempt::Sort {} + impl Trace for [T; N] where T: Trace,