Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "concread"
version = "0.5.7"
version = "0.5.8"
authors = ["William Brown <william@blackhats.net.au>"]
edition = "2021"
description = "Concurrently Readable Data-Structures for Rust"
Expand Down Expand Up @@ -45,32 +45,32 @@ arcache-is-hashtrie = ["arcache"]
simd_support = []

[dependencies]
ahash = { version = "0.8", optional = true }
foldhash = { version = "0.1.5", optional = true }
ahash = { version = "0.8.12", optional = true }
foldhash = { version = "0.2.0", optional = true }
crossbeam-utils = { version = "0.8.21", optional = true }
crossbeam-epoch = { version = "0.9.11", optional = true }
crossbeam-epoch = { version = "0.9.18", optional = true }
crossbeam-queue = { version = "0.3.12", optional = true }
dhat = { version = "0.3.3", optional = true }
lru = { version = "0.13", optional = true }
lru = { version = "0.16.3", optional = true }
serde = { version = "1.0", optional = true }
smallvec = { version = "1.14", optional = true }
smallvec = { version = "1.15.1", optional = true }
sptr = "0.3"
tokio = { version = "1", features = ["sync"], optional = true }
tracing = "0.1"
tokio = { version = "1.49.0", features = ["sync"], optional = true }
tracing = "0.1.44"

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
rand = "0.9"
tracing-subscriber = { version = "0.3", features = [
criterion = { version = "0.8.1", features = ["html_reports"] }
rand = "0.9.2"
tracing-subscriber = { version = "0.3.22", features = [
"env-filter",
"std",
"fmt",
] }
uuid = "1"
uuid = ">=1.19.0"
function_name = "0.3"
serde_json = "1"
tokio = { version = "1", features = ["rt", "macros"] }
proptest = "1.0.0"
serde_json = ">=1.0.149"
tokio = { version = "1.49.0", features = ["rt", "macros"] }
proptest = "1.9.0"

[[bench]]
name = "hashmap_benchmark"
Expand Down
8 changes: 4 additions & 4 deletions benches/arccache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ where
match self {
AccessPattern::Random(min, max) => {
let mut rng = thread_rng();
rng.gen_range(min.clone()..max.clone())
rng.gen_range(*min..*max)
}
}
}
Expand Down Expand Up @@ -209,10 +209,10 @@ where
.into_iter()
.map(|cache| {
// Build the threads.
let back_set = backing_set.clone();
let back_set_delay = backing_set_delay.clone();
let pat = access_pattern.clone();
thread::spawn(move || tlocal_multi_thread_worker(cache, back_set, back_set_delay, pat))
thread::spawn(move || {
tlocal_multi_thread_worker(cache, backing_set, backing_set_delay, pat)
})
})
.collect();

Expand Down
43 changes: 22 additions & 21 deletions benches/hashmap_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ extern crate criterion;
extern crate rand;

use concread::hashmap::*;
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use rand::{thread_rng, Rng};
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use rand::{rng, Rng};
use std::hint::black_box;

// ranges of counts for different benchmarks (MINs are inclusive, MAXes exclusive):
const INSERT_COUNT_MIN: usize = 120;
Expand Down Expand Up @@ -168,7 +169,7 @@ criterion_main!(insert, remove, search);
fn insert_vec<V: Clone + Sync + Send + 'static>(
map: &mut HashMap<u32, V>,
list: Vec<(u32, V)>,
) -> HashMapWriteTxn<u32, V> {
) -> HashMapWriteTxn<'_, u32, V> {
let mut write_txn = map.write();
for (key, val) in list.into_iter() {
write_txn.insert(key, val);
Expand All @@ -178,7 +179,7 @@ fn insert_vec<V: Clone + Sync + Send + 'static>(

fn remove_vec<'a, V: Clone + Sync + Send + 'static>(
map: &'a mut HashMap<u32, V>,
list: &Vec<u32>,
list: &[u32],
) -> HashMapWriteTxn<'a, u32, V> {
let mut write_txn = map.write();
for i in list.iter() {
Expand All @@ -187,7 +188,7 @@ fn remove_vec<'a, V: Clone + Sync + Send + 'static>(
write_txn
}

fn search_vec<V: Clone + Sync + Send + 'static>(map: &HashMap<u32, V>, list: &Vec<u32>) {
fn search_vec<V: Clone + Sync + Send + 'static>(map: &HashMap<u32, V>, list: &[u32]) {
let read_txn = map.read();
for i in list.iter() {
read_txn.get(black_box(i));
Expand Down Expand Up @@ -242,23 +243,23 @@ struct Struct {
}

fn prepare_insert<V: Clone + Sync + Send + 'static>(value: V) -> (HashMap<u32, V>, Vec<(u32, V)>) {
let mut rng = thread_rng();
let count = rng.gen_range(INSERT_COUNT_MIN..INSERT_COUNT_MAX);
let mut rng = rng();
let count = rng.random_range(INSERT_COUNT_MIN..INSERT_COUNT_MAX);
let mut list = Vec::with_capacity(count);
for _ in 0..count {
list.push((
rng.gen_range(0..INSERT_COUNT_MAX << 8) as u32,
value.clone(),
rng.random_range(0..INSERT_COUNT_MAX << 8) as u32,
value.to_owned(),
));
}
(HashMap::new(), list)
}

/// Prepares a remove benchmark with values in the HashMap being clones of the 'value' parameter
fn prepare_remove<V: Clone + Sync + Send + 'static>(value: V) -> (HashMap<u32, V>, Vec<u32>) {
let mut rng = thread_rng();
let insert_count = rng.gen_range(INSERT_COUNT_FOR_REMOVE_MIN..INSERT_COUNT_FOR_REMOVE_MAX);
let remove_count = rng.gen_range(REMOVE_COUNT_MIN..REMOVE_COUNT_MAX);
let mut rng = rng();
let insert_count = rng.random_range(INSERT_COUNT_FOR_REMOVE_MIN..INSERT_COUNT_FOR_REMOVE_MAX);
let remove_count = rng.random_range(REMOVE_COUNT_MIN..REMOVE_COUNT_MAX);
let map = HashMap::new();
let mut write_txn = map.write();
for i in random_order(insert_count, insert_count).iter() {
Expand All @@ -271,10 +272,10 @@ fn prepare_remove<V: Clone + Sync + Send + 'static>(value: V) -> (HashMap<u32, V
}

fn prepare_search<V: Clone + Sync + Send + 'static>(value: V) -> (HashMap<u32, V>, Vec<u32>) {
let mut rng = thread_rng();
let insert_count = rng.gen_range(INSERT_COUNT_FOR_SEARCH_MIN..INSERT_COUNT_FOR_SEARCH_MAX);
let mut rng = rng();
let insert_count = rng.random_range(INSERT_COUNT_FOR_SEARCH_MIN..INSERT_COUNT_FOR_SEARCH_MAX);
let search_limit = insert_count * SEARCH_SIZE_NUMERATOR / SEARCH_SIZE_DENOMINATOR;
let search_count = rng.gen_range(SEARCH_COUNT_MIN..SEARCH_COUNT_MAX);
let search_count = rng.random_range(SEARCH_COUNT_MIN..SEARCH_COUNT_MAX);

// Create a HashMap with elements 0 through insert_count(-1)
let map = HashMap::new();
Expand All @@ -287,28 +288,28 @@ fn prepare_search<V: Clone + Sync + Send + 'static>(value: V) -> (HashMap<u32, V
// Choose 'search_count' numbers from [0,search_limit) randomly to be searched in the created map.
let mut list = Vec::with_capacity(search_count);
for _ in 0..search_count {
list.push(rng.gen_range(0..search_limit as u32));
list.push(rng.random_range(0..search_limit as u32));
}
(map, list)
}

/// Returns a Vec of n elements from the range [0,up_to) in random order without repetition
fn random_order(up_to: usize, n: usize) -> Vec<u32> {
let mut rng = thread_rng();
let mut rng = rng();
let mut order = Vec::with_capacity(n);
let mut generated = vec![false; up_to];
let mut remaining = n;
let mut remaining_elems = up_to;
while remaining > 0 {
let mut r = rng.gen_range(0..remaining_elems);
let mut r = rng.random_range(0..remaining_elems);
// find the r-th yet nongenerated number:
for i in 0..up_to {
if generated[i] {
for (i, value) in generated.iter_mut().enumerate().take(up_to) {
if *value {
continue;
}
if r == 0 {
order.push(i as u32);
generated[i] = true;
*value = true;
break;
}
r -= 1;
Expand Down
9 changes: 3 additions & 6 deletions src/arcache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ impl<
// * everything hit must be in main cache now, so bring these
// all to the relevant item heads.
// * Why do this last? Because the write is the "latest" we want all the fresh
// written items in the cache over the "read" hits, it gives us some aprox
// written items in the cache over the "read" hits, it gives us some appximation
// of time ordering, but not perfect.

// Find the item in the cache.
Expand Down Expand Up @@ -1261,7 +1261,7 @@ impl<
//
// keep removing from rec until == p OR delta == 0, and if delta remains, then remove from freq.
//
// Remember P is "the maximum size of recent" or "presure on recent". If P is max then
// Remember P is "the maximum size of recent" or "pressure on recent". If P is max then
// we are pressuring churning on recent but not freq, so evict in freq.
//
// If P is toward 0 that means all our pressure is in frequent and we evicted things we
Expand Down Expand Up @@ -1938,10 +1938,9 @@ impl<
}

#[cfg(test)]
pub(crate) fn peek_cache<Q: ?Sized>(&self, k: &Q) -> CacheState
pub(crate) fn peek_cache<Q: ?Sized + Hash + Eq + Ord>(&self, k: &Q) -> CacheState
where
K: Borrow<Q>,
Q: Hash + Eq + Ord,
{
if let Some(v) = self.cache.get(k) {
(*v).to_state()
Expand Down Expand Up @@ -3154,7 +3153,6 @@ mod tests {
}

#[allow(dead_code)]

pub static RUNNING: AtomicBool = AtomicBool::new(false);

#[cfg(test)]
Expand Down Expand Up @@ -3192,7 +3190,6 @@ mod tests {
RUNNING.store(true, Ordering::Relaxed);

let handles: Vec<_> = (0..thread_count)
.into_iter()
.map(|_| {
// Build the threads.
let cache = arc.clone();
Expand Down
2 changes: 1 addition & 1 deletion src/arcache/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fmt::Debug;
/// Write statistics for ARCache
pub trait ARCacheWriteStat<K> {
// RW phase trackers
/// Record that a cache clear event occured.
/// Record that a cache clear event occurred.
///
/// Phase - write transaction open
fn cache_clear(&mut self) {}
Expand Down
20 changes: 10 additions & 10 deletions src/hashmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ mod tests {
assert!(!snap.contains_key(&20));
assert_eq!(snap.len(), 2);
assert!(!snap.is_empty());
assert!(snap.iter().find(|(_k, v)| **v == 10).is_some());
assert!(snap.iter().any(|(_k, v)| *v == 10));
assert_eq!(snap.values().count(), 2);
assert_eq!(snap.keys().count(), 2);
}
Expand Down Expand Up @@ -311,17 +311,17 @@ mod tests {
fn test_hashmap_keys() {
let hmap: HashMap<usize, usize> = vec![(10, 10), (15, 15), (20, 20)].into_iter().collect();
let hmap_read = hmap.read();
assert!(hmap_read.keys().find(|&&x| x == 10).is_some());
assert!(hmap_read.keys().any(|&x| x == 10));
let hmap_write = hmap.write();
assert!(hmap_write.keys().find(|&&x| x == 10).is_some());
assert!(hmap_write.keys().any(|&x| x == 10));
}
#[test]
fn test_hashmap_values() {
let hmap: HashMap<usize, usize> = vec![(10, 11), (15, 15), (20, 20)].into_iter().collect();
let hmap_read = hmap.read();
assert!(hmap_read.values().find(|&&x| x == 11).is_some());
assert!(hmap_read.values().any(|&x| x == 11));
let hmap_write = hmap.write();
assert!(hmap_write.values().find(|&&x| x == 11).is_some());
assert!(hmap_write.values().any(|&x| x == 11));
}

#[test]
Expand All @@ -332,11 +332,11 @@ mod tests {
assert!(!hmap_write_snapshot.is_empty());
assert_eq!(hmap_write_snapshot.len(), 3);
assert!(hmap_write_snapshot.contains_key(&10));
assert!(hmap_write_snapshot.values().find(|&&x| x == 11).is_some());
assert!(hmap_write_snapshot.values().find(|&&x| x == 10).is_none());
assert!(hmap_write_snapshot.keys().find(|&&x| x == 10).is_some());
assert!(hmap_write_snapshot.keys().find(|&&x| x == 11).is_none());
assert!(hmap_write_snapshot.keys().find(|&&x| x == 10).is_some());
assert!(hmap_write_snapshot.values().any(|&x| x == 11));
assert!(hmap_write_snapshot.values().all(|&x| x != 10));
assert!(hmap_write_snapshot.keys().any(|&x| x == 10));
assert!(hmap_write_snapshot.keys().all(|&x| x != 11));
assert!(hmap_write_snapshot.keys().any(|&x| x == 10));
assert!(hmap_write_snapshot.iter().count() == 3);
}
}
6 changes: 3 additions & 3 deletions src/hashtrie/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ mod tests {
assert!(hmap_w1.is_empty());
hmap_w1.insert(10, 10);
// just coverage things
hmap_w1.extend([(15, 15)].into_iter());
hmap_w1.extend([(15, 15)]);
assert!(!hmap_w1.is_empty());
hmap_w1.commit();

Expand Down Expand Up @@ -294,9 +294,9 @@ mod tests {
fn test_hashtrie_keys() {
let hmap: HashTrie<usize, usize> = vec![(10, 10), (15, 15), (20, 20)].into_iter().collect();
let hmap_read = hmap.read();
assert!(hmap_read.keys().find(|&&x| x == 10).is_some());
assert!(hmap_read.keys().any(|&x| x == 10));
let hmap_write = hmap.write();
assert!(hmap_write.keys().find(|&&x| x == 10).is_some());
assert!(hmap_write.keys().any(|&x| x == 10));
}

#[test]
Expand Down
8 changes: 3 additions & 5 deletions src/internals/bptree/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ mod tests {
}

fn create_leaf_node_full(vbase: usize) -> *mut Node<usize, usize> {
assert!(vbase % 10 == 0);
assert!(vbase.is_multiple_of(10));
let node = Node::new_leaf(1);
{
let nmut = leaf_ref!(node, usize, usize);
Expand Down Expand Up @@ -2296,8 +2296,8 @@ mod tests {
#[test]
fn test_bptree2_cursor_remove_15() {
// Test leaf borrow right.
let lnode = create_leaf_node(10) as *mut Node<usize, usize>;
let rnode = create_leaf_node_full(20) as *mut Node<usize, usize>;
let lnode = create_leaf_node(10);
let rnode = create_leaf_node_full(20);
let root = Node::new_branch(0, lnode, rnode);
let sb = SuperBlock::new_test(1, root as *mut Node<usize, usize>);
let mut wcurs = sb.create_writer();
Expand Down Expand Up @@ -2647,7 +2647,6 @@ mod tests {
#[test]
fn test_bptree2_cursor_split_off_lt_clone_stress() {
// Can't proceed as the "fake" tree we make is invalid.
debug_assert!(L_CAPACITY >= 4);
let outer: [usize; 4] = [0, 100, 200, 300];
let inner: [usize; 4] = [0, 10, 20, 30];
for i in outer.iter() {
Expand All @@ -2663,7 +2662,6 @@ mod tests {
#[cfg(not(feature = "skinny"))]
#[test]
fn test_bptree2_cursor_split_off_lt_stress() {
debug_assert!(L_CAPACITY >= 4);
let outer: [usize; 4] = [0, 100, 200, 300];
let inner: [usize; 4] = [0, 10, 20, 30];
for i in outer.iter() {
Expand Down
2 changes: 1 addition & 1 deletion src/internals/bptree/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ mod tests {
use std::ops::Bound::*;

fn create_leaf_node_full(vbase: usize) -> *mut Node<usize, usize> {
assert!(vbase % 10 == 0);
assert!(vbase.is_multiple_of(10));
let node = Node::new_leaf(0);
{
let nmut = leaf_ref!(node, usize, usize);
Expand Down
4 changes: 2 additions & 2 deletions src/internals/bptree/mutiter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ mod tests {
use crate::internals::lincowcell::LinCowCellCapable;

fn create_leaf_node_full(vbase: usize) -> *mut Node<usize, usize> {
assert!(vbase % 10 == 0);
assert!(vbase.is_multiple_of(10));
let node = Node::new_leaf(0);
{
let nmut = leaf_ref!(node, usize, usize);
Expand All @@ -103,7 +103,7 @@ mod tests {
fn test_bptree2_iter_mutrangeiter_1() {
let node = create_leaf_node_full(10);

let sb = SuperBlock::new_test(1, node as *mut Node<usize, usize>);
let sb = SuperBlock::new_test(1, node);
let mut wcurs = sb.create_writer();

let bounds: (Bound<usize>, Bound<usize>) = (Unbounded, Unbounded);
Expand Down
Loading
Loading