Skip to content

Commit

Permalink
Refactor stress test
Browse files Browse the repository at this point in the history
  • Loading branch information
Khojasteh committed Feb 12, 2024
1 parent 5d8a97d commit 7ae991d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 93 deletions.
54 changes: 1 addition & 53 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
name = "uf_rush"
authors = ["Kambiz Khojasteh"]
description = "A lock-free, thread-safe implementation of the Union-Find (Disjoint-Set) data structure."
version = "0.1.1"
keywords = ["union-find", "disjoint-sets", "data-structure", "concurrency", "parallel-computing", "lock-free", "thread-safe", "algorithm"]
categories = ["data-structures", "algorithms", "concurrency"]
version = "0.2.0"
edition = "2021"
license = "MIT"
readme = "README.md"
repository = "https://github.com/khojasteh/uf_rush"
documentation = "https://docs.rs/uf_rush/0.1.1"
documentation = "https://docs.rs/uf_rush/0.2.0"

[dev-dependencies]
rand = "0.8.5"
rayon = "1.8.1"
rand = "0.8"

[profile.test]
opt-level = 3
73 changes: 37 additions & 36 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ fn rank(n: usize) -> usize {
#[cfg(test)]
mod tests {
use super::*;
use rand::prelude::*;
use std::collections::HashSet;
use std::sync::Arc;
use std::thread;

Expand Down Expand Up @@ -327,45 +329,44 @@ mod tests {

#[test]
fn stress_test() {
use rand::prelude::*;
use std::sync::{Arc, Barrier};
use std::thread;

let num_elements = 1_00_000; // Adjust based on the system's capability

let elements = 1 << 9;

// Preparing a pool of element pairs for unification
let mut pairs = Vec::new();
// Make sure everythin is connected
for i in 0..=elements {
let i = i % elements;
pairs.push((i, i + 1));
}
// Add random edges to the graph
for i in 0..num_elements - 1 {
let source = rand::random::<usize>() % elements;
let target = rand::random::<usize>() % elements;
pairs.push((source, target));
let node_count = 500;
let mut rng = rand::thread_rng();
let mut edges = HashSet::with_capacity(node_count + node_count / 10);

// Add edges to form a cycle
edges.extend((0..node_count).map(|n| (n, (n + 1) % node_count)));

// Add some extra random edges
for _ in edges.len()..edges.capacity() {
let u = rng.gen_range(0..node_count);
let v = rng.gen_range(0..node_count);
if u != v {
edges.insert((u, v));
}
}

for i in 0..1000 {
// Shuffle pairs to randomize access patterns
let uf = Arc::new(UFRush::new(elements + 1));
use rand::{thread_rng, Rng};
use rayon::prelude::*;
let mut rng = thread_rng();
let total_unites = AtomicUsize::new(0);
let total_unites = &total_unites;
pairs.shuffle(&mut rng);

pairs.par_iter().for_each(|(x, y)| {
if uf.unite(*x, *y) {
total_unites.fetch_add(1, Ordering::Relaxed);
}
});
let mut edges: Vec<_> = edges.into_iter().collect();
for _ in 0..100 {
edges.shuffle(&mut rng);
let uf = Arc::new(UFRush::new(node_count));

// Spawn threads and collect their join handles
let handles: Vec<_> = edges
.iter()
.map(|&(u, v)| {
let uf = Arc::clone(&uf);
thread::spawn(move || uf.unite(u, v))
})
.collect();

// Wait for all threads to finish; count the number of unites
let total_unites = handles
.into_iter()
.map(|handle| handle.join().unwrap())
.filter(|&united| united)
.count();

assert_eq!(total_unites.load(Ordering::SeqCst), elements);
assert_eq!(total_unites, node_count - 1);
}
}

Expand Down

0 comments on commit 7ae991d

Please sign in to comment.