diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3dbf5ff..48b00c0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Boost - run: sudo apt-get install -y libboost-all-dev + run: sudo apt-get update && sudo apt-get install -y libboost-all-dev - name: Get submodules run: git submodule init && git submodule update - name: Build diff --git a/.gitignore b/.gitignore index efd9c17..5ed9274 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /target /output +/scripts/output Cargo.lock /venv src/cpp-ring-queues-research/benchmarks.sh diff --git a/.gitmodules b/.gitmodules index fe0feb3..0f8702a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "queues/moodycamel_cpp/cpp_src/concurrentqueue"] - path = queues/moodycamel_cpp/cpp_src/concurrentqueue +[submodule "data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue"] + path = data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git diff --git a/Cargo.toml b/Cargo.toml index 857f03d..a986b91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,33 +2,34 @@ resolver = "2" members = [ "benchmark_core", - "queues/array_queue", - "queues/atomic_queue", - "queues/basic_queue", - "queues/bbq", - "queues/boost_queue_cpp", - "queues/bounded_concurrent_queue", - "queues/unbounded_concurrent_queue", - "queues/bounded_ringbuffer", - "queues/faaa_queue", - "queues/faaa_queue_cpp", - "queues/lcrq_cpp", - "queues/lcrq", - "queues/lprq_cpp", - "queues/lprq", - "queues/lf_queue", - "queues/lockfree_queue", - "stacks/lockfree_stack", - "queues/moodycamel_cpp", - "queues/ms_queue", - "queues/scc_queue", - "stacks/scc_stack", - "queues/scc2_queue", - "stacks/scc2_stack", - "queues/seg_queue", - "queues/tz_queue_leak", - "queues/tz_queue_hp", - "queues/wf_queue", + "data_structures/fifo_queues/array_queue", + "data_structures/fifo_queues/atomic_queue", + "data_structures/fifo_queues/basic_queue", + "data_structures/fifo_queues/bbq", + "data_structures/fifo_queues/boost_queue_cpp", + "data_structures/fifo_queues/bounded_concurrent_queue", + "data_structures/fifo_queues/unbounded_concurrent_queue", + "data_structures/fifo_queues/bounded_ringbuffer", + "data_structures/fifo_queues/faaa_queue", + "data_structures/fifo_queues/faaa_queue_cpp", + "data_structures/fifo_queues/lcrq_cpp", + "data_structures/fifo_queues/lcrq", + "data_structures/fifo_queues/lprq_cpp", + "data_structures/fifo_queues/lprq", + "data_structures/fifo_queues/lf_queue", + "data_structures/fifo_queues/lockfree_queue", + "data_structures/stacks/lockfree_stack", + "data_structures/fifo_queues/moodycamel_cpp", + "data_structures/fifo_queues/ms_queue", + "data_structures/fifo_queues/scc_queue", + "data_structures/stacks/scc_stack", + "data_structures/fifo_queues/scc2_queue", + "data_structures/stacks/scc2_stack", + "data_structures/fifo_queues/seg_queue", + "data_structures/fifo_queues/tz_queue_leak", + "data_structures/fifo_queues/tz_queue_hp", + "data_structures/fifo_queues/wf_queue", + "data_structures/priority_queues/basic_priority_queue", ] [workspace.dependencies] diff --git a/benchmark_core/src/arguments.rs b/benchmark_core/src/arguments.rs index 738b4ec..598fb87 100644 --- a/benchmark_core/src/arguments.rs +++ b/benchmark_core/src/arguments.rs @@ -1,139 +1,216 @@ use clap::{ArgAction, Args as ClapArgs, Parser, Subcommand}; use std::fmt::Display; -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -pub struct Args { +/// General arguments for all benchmarks +#[derive(ClapArgs, Debug, Clone)] +pub struct GeneralArgs { /// Duration of each benchmark #[arg(short, long, default_value_t = 10)] pub time_limit: u64, - /// Attemps to only use on socket. Specific for the developers test environment. + + /// Attemps to only use one socket. Specific for the developers test environment. #[arg(short, long, default_value_t = true, action = ArgAction::SetFalse)] pub one_socket: bool, + /// How many times the chosen benchmark should be run. #[arg(short, long, default_value_t = 1)] pub iterations: u32, - /// Count empty pop operations. Off by default. - #[arg(short, long, default_value_t = false)] - pub empty_pops: bool, - /// Set the size of the bounded queues. - #[arg(short, long, default_value_t = 10000)] - pub queue_size: u32, + /// Set the amount of floating point numbers generated between each operation. Default is 10. #[arg(short, long, default_value_t = 10)] pub delay: u64, + /// Set the output path for the result files. #[arg(long = "path", default_value_t = String::from("./output"))] pub path_output: String, - /// Choose which benchmark to run. - #[command(subcommand)] - pub benchmark: Benchmarks, + /// If set to true, benchmark will output to stdout instead of to files. #[arg(long = "write-stdout", default_value_t = false)] pub write_to_stdout: bool, - /// Prefill the queue with values before running the benchmark. - #[arg(short, long, default_value_t = 0)] - pub prefill_amount: u64, + /// Write benchmark configuration and hardware info to a separate file. #[arg(long, default_value_t = false, action = ArgAction::SetTrue)] pub print_info: bool, + #[cfg(feature = "memory_tracking")] /// The interval of which memory tracking will update [ms]. #[arg(long, default_value_t = 50)] pub memory_tracking_interval: u64, } -/// Possible benchmark types. +/// Arguments for the FIFO Queue benchmark types +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct FifoQueueArgs { + /// Count empty pop operations. Off by default. + #[arg(short, long, default_value_t = false)] + pub empty_pops: bool, + + /// Set the size of the bounded queues. + #[arg(short, long, default_value_t = 10000)] + pub queue_size: u32, + + /// The runner to use for the benchmark + #[command(subcommand)] + pub benchmark_runner: FifoQueueBenchmarks, + + /// Prefill the FIFO Queue with default values before running the benchmark. + #[arg(short, long, default_value_t = 0)] + pub prefill_amount: u64, + + /// General arguments agnostic to the FIFO Queue + #[command(flatten)] + pub general_args: GeneralArgs, +} + +/// Benchmark runners for FIFO Queues. #[derive(Subcommand, Debug)] -pub enum Benchmarks { - /// ProdCon throughput test. Decide amount of producers and consumers using flags. - ProdCon(ProdConArgs), - /// A test where each thread performs both consume and produce based on a random floating point - /// value. Spread is decided using the `--spread` flag. - EnqDeq(EnqDeqArgs), - EnqDeqPairs(EnqDeqPairsArgs), - BFS(BFSArgs), +pub enum FifoQueueBenchmarks { + /// A benchmark for measuring throughput using producers and consumers that + /// are each bound to a thread + ProdCon(FifoQueueProdConArgs), + + /// A benchmark measuring throughput where a thread will switch between + /// producing and consuming + EnqDeq(FifoQueueEnqDeqArgs), + + /// A benchmark measuring throughput where a thread will enqueue an item + /// and then immediately dequeue it + EnqDeqPairs(FifoQueueEnqDeqPairsArgs), + + /// Benchmarks how fast the FIFO Queue can complete a breadth-first search + /// on a graph + BFS(FifoQueueBFSArgs), } #[derive(ClapArgs, Debug)] -pub struct ProdConArgs { - /// Amount of producers to be used for basic throughput test. +pub struct FifoQueueProdConArgs { + /// Amount of producers to be used #[arg(short, long, default_value_t = 20)] pub producers: usize, - /// Amount of consumers to be used for basic throughput test. + + /// Amount of consumers to be used #[arg(short, long, default_value_t = 20)] pub consumers: usize, } + #[derive(ClapArgs, Debug)] -pub struct EnqDeqArgs { +pub struct FifoQueueEnqDeqArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, + /// Decide the spread of producers/consumers for the pingpong benchmark. /// Ex. 0.3 means 30% produce 70% consume. #[arg(long = "spread", default_value_t = 0.5)] pub spread: f64, } + #[derive(ClapArgs, Debug)] -pub struct EnqDeqPairsArgs { +pub struct FifoQueueEnqDeqPairsArgs { /// Set the thread count for the pingpong benchmark. #[arg(long = "thread-count", default_value_t = 20)] pub thread_count: usize, } + #[derive(ClapArgs, Debug)] -pub struct BFSArgs { +pub struct FifoQueueBFSArgs { #[arg(short, long, default_value_t = 20)] pub thread_count: usize, + #[arg(short, long)] pub graph_file: String, + #[arg(short, long, default_value_t = false)] pub no_verify: bool, } + +/// Arguments for the Priority Queue benchmark types +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct PriorityQueueArgs { + /// Set the size of the bounded queues. + #[arg(short, long, default_value_t = 10000)] + pub queue_size: u32, + + /// The runner to use for the benchmark + #[command(subcommand)] + pub benchmark_runner: PriorityQueueBenchmarks, + + /// Prefill the FIFO Queue with default values before running the benchmark. + #[arg(short, long, default_value_t = 0)] + pub prefill_amount: u64, + + /// General arguments agnostic to the Priority Queue + #[command(flatten)] + pub general_args: GeneralArgs, +} + +/// Benchmark runners for priority queues. +#[derive(Subcommand, Debug)] +pub enum PriorityQueueBenchmarks { + /// A benchmark for measuring throughput using producers and consumers that + /// are each bound to a thread + ProdCon(PQProdConArgs), +} + +#[derive(ClapArgs, Debug)] +pub struct PQProdConArgs { + /// Amount of producers to be used for basic throughput test. + #[arg(short, long, default_value_t = 20)] + pub producers: usize, + + /// Amount of consumers to be used for basic throughput test. + #[arg(short, long, default_value_t = 20)] + pub consumers: usize, +} + /// This is used to write the benchmark type to the output. /// That is why the arguments are discarded. -impl Display for Benchmarks { +impl Display for FifoQueueBenchmarks { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Benchmarks::ProdCon(_) => write!(f, "ProdCon"), - Benchmarks::EnqDeq(_) => write!(f, "EnqDeq"), - Benchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), + FifoQueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + FifoQueueBenchmarks::EnqDeq(_) => write!(f, "EnqDeq"), + FifoQueueBenchmarks::EnqDeqPairs(_) => write!(f, "EnqDeqPairs"), // #[cfg(feature = "bfs")] - Benchmarks::BFS(_) => write!(f, "BFS"), + FifoQueueBenchmarks::BFS(_) => write!(f, "BFS"), } } } + +/// This is used to write the benchmark type to the output. +/// That is why the arguments are discarded. +impl Display for PriorityQueueBenchmarks { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PriorityQueueBenchmarks::ProdCon(_) => write!(f, "ProdCon"), + } + } +} + /// This is used in the print_info function. -impl Display for Args { +impl Display for GeneralArgs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Time limit: {}", self.time_limit)?; writeln!(f, "One socket?: {}", self.one_socket)?; writeln!(f, "Iterations: {}", self.iterations)?; - writeln!(f, "Queue size: {}", self.queue_size)?; writeln!(f, "Delay: {}", self.delay)?; writeln!(f, "Output path: {}", self.path_output)?; - writeln!(f, "Benchmark: {:?}", self.benchmark)?; writeln!(f, "Write to stdout: {}", self.write_to_stdout)?; - writeln!(f, "prefill amount: {}", self.prefill_amount)?; Ok(()) } } /// Implemented so that tests are easier to write. -impl Default for Args { +impl Default for GeneralArgs { fn default() -> Self { - Args { - prefill_amount: 0, + GeneralArgs { time_limit: 1, one_socket: true, iterations: 1, - empty_pops: false, - queue_size: 10000, delay: 10, path_output: "".to_string(), - benchmark: Benchmarks::ProdCon(ProdConArgs { - producers: 5, - consumers: 5, - }), write_to_stdout: true, print_info: false, #[cfg(feature = "memory_tracking")] @@ -141,3 +218,38 @@ impl Default for Args { } } } + +/// Implemented for easier testing +impl Default for FifoQueueArgs { + fn default() -> Self { + FifoQueueArgs { + empty_pops: false, + queue_size: 10000, + benchmark_runner: FifoQueueBenchmarks::ProdCon( + FifoQueueProdConArgs { + producers: 20, + consumers: 20, + }, + ), + prefill_amount: 1000, + general_args: GeneralArgs::default(), + } + } +} + +/// Implemented for easier testing +impl Default for PriorityQueueArgs { + fn default() -> Self { + PriorityQueueArgs { + queue_size: 10000, + benchmark_runner: PriorityQueueBenchmarks::ProdCon( + PQProdConArgs { + producers: 20, + consumers: 20, + }, + ), + prefill_amount: 1000, + general_args: GeneralArgs::default(), + } + } +} diff --git a/benchmark_core/src/benchmarks.rs b/benchmark_core/src/benchmarks.rs index 2a1369c..359149e 100644 --- a/benchmark_core/src/benchmarks.rs +++ b/benchmark_core/src/benchmarks.rs @@ -1,397 +1,4 @@ -#[cfg(feature = "memory_tracking")] -use jemalloc_ctl::{epoch, stats}; -use log::{debug, error, trace}; -#[allow(unused_imports)] -use crate::arguments::{Args, Benchmarks}; -#[allow(unused_imports)] -use crate::traits::ConcurrentQueue; -use std::fs::OpenOptions; -use std::io::Write; -#[allow(unused_imports)] -use std::sync::atomic::AtomicBool; -use sysinfo::System; - -pub mod prod_con; -pub mod enq_deq; -pub mod enq_deq_pairs; -pub mod bfs; - -/// Benchmark config struct -/// Needs to be fully filled for benchmarks to be able to run. -pub struct BenchConfig { - pub args: Args, - pub date_time: String, - pub benchmark_id: String, - pub output_filename: String, -} - -/// Create the queue, and run the selected benchmark a set of times -pub fn benchmark_queue(bench_conf: &BenchConfig, queue_name: &str) -> Result<(), std::io::Error> -where - Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send -{ - // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on - let mut runner: Box Result<(), std::io::Error>> = match &bench_conf.args.benchmark { - Benchmarks::ProdCon(_) => Box::new(move |q, bench_conf| prod_con::benchmark_prod_con(q, bench_conf)), - Benchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| enq_deq::benchmark_enq_deq(q, bench_conf)), - Benchmarks::EnqDeqPairs(_) => Box::new(move |q, bench_conf| enq_deq_pairs::benchmark_enq_deq_pairs(q, bench_conf)), - Benchmarks::BFS(args) => { - let (graph, seq_ret_vec, start_node) = - bfs::pre_bfs_work( - Q::new(bench_conf.args.queue_size as usize), - args, - ); - Box::new(move |q, _conf| bfs::benchmark_bfs( - q, - &graph, - bench_conf, - &seq_ret_vec, - start_node - ) - ) - }, - }; - - for _current_iteration in 0..bench_conf.args.iterations { - // Create the queue. - let test_q: Q = Q::new(bench_conf.args.queue_size as usize); - - // Start memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - let (done, mem_thread_handle) = { - let done = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); - let handle = create_mem_tracking_thread( - bench_conf, - _current_iteration, - &test_q, - &done - )?; - (done, handle) - }; - - // Execute the benchmark - runner(test_q, bench_conf)?; - - // Join the thread again - debug!("Queue should have been dropped now."); - - // Stop memory tracking (if enabled) - #[cfg(feature = "memory_tracking")] - { - use std::sync::atomic::Ordering; - debug!("Joining memory thread."); - done.store(true, Ordering::Relaxed); - if let Err(e) = mem_thread_handle.join().unwrap() { - log::error!("Couldn't join memory tracking thread: {}", e); - } - } - } - - if bench_conf.args.print_info { - print_info(queue_name.to_string(), bench_conf)?; - } - - Ok(()) -} - - -#[cfg(feature = "memory_tracking")] -pub fn create_mem_tracking_thread( - bench_conf: &BenchConfig, - _current_iteration: u32, - test_q: &Q, - _done: &std::sync::Arc) --> Result>, std::io::Error> -where - Q: ConcurrentQueue -{ - - use std::sync::atomic::Ordering; - // TODO: Check if core stuff is possible here as well. - // let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - // if *is_one_socket { - // core = core_iter.next().unwrap(); - // } - let _done = std::sync::Arc::clone(_done); - let benchmark_id = bench_conf.benchmark_id.clone(); - let bench_type = format!("{}", bench_conf.args.benchmark); - let to_stdout = bench_conf.args.write_to_stdout; - let queue_type = test_q.get_id(); - - // Create file if printing to stdout is disabled - let top_line = "Memory Allocated,Queuetype,Benchmark,Test ID,Iteration"; - let mut memfile = if !to_stdout { - let output_filename = format!("{}/mem{}", bench_conf.args.path_output, bench_conf.date_time); - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&output_filename)?; - if _current_iteration == 0 { - writeln!(file, "{}", top_line)?; - } - Some(file) - } else { - if _current_iteration == 0 { - println!("{}", top_line); - } - None - }; - - // Spawn thread to check total memory allocated every 50ms - let interval = bench_conf.args.memory_tracking_interval; - debug!("Spawning memory thread."); - Ok(std::thread::spawn(move|| -> Result<(), std::io::Error>{ - while !_done.load(Ordering::Relaxed) { - // Update stats - if let Err(e) = epoch::advance() { - eprintln!("Error occured while advancing epoch: {}", e); - } - // Get allocated bytes - let allocated = stats::allocated::read().unwrap(); - - let output = format!("{},{},{},{},{}", allocated, queue_type, bench_type, &benchmark_id, _current_iteration); - - match &mut memfile { - Some(file) => writeln!(file, "{}", output)?, - None => println!("{}", output), - } - - std::thread::sleep(std::time::Duration::from_millis(interval)); - } - Ok(()) - })) - -} - -/// Calculates the fairness based on paper: -/// [A Study of the Behavior of Synchronization Methods in Commonly Used Languages and Systems](https://ieeexplore.ieee.org/document/6569906). -pub fn calc_fairness(ops_per_thread: Vec) -> f64 { - debug!("Calculating fairness"); - let sum: usize = ops_per_thread.iter().sum(); - - let length: f64 = ops_per_thread.len() as f64; - debug!("The vector {:?}", ops_per_thread); - debug!("Sum: {}, Length: {}",sum, length); - - // The thread that does the least amount of ops - let minop: f64 = match ops_per_thread.iter().min() { - Some(&val) => val as f64, - None => { - error!("No record of operations: {:?}", ops_per_thread); - panic!(); - } - }; - trace!("Minop fairness: {}", minop); - - // The thread that does the most amount of ops - let maxop: f64 = match ops_per_thread.iter().max() { - Some(&val) => val as f64, - None => { - error!("No record of operations: {:?}", ops_per_thread); - panic!(); - } - }; - trace!("Maxop fairness: {}", maxop); - - let fairness: f64 = f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); - - debug!("Calculated fairness: {}", fairness); - fairness -} - - - -/// Function to print the specifications of the hardware used and the benchmnark configs that ran -pub fn print_info(queue: String, bench_conf: &BenchConfig) -> Result<(), std::io::Error>{ - // Create file if printing to stdout is disabled - if bench_conf.args.write_to_stdout { - return Ok(()); - } - let memfile = { - let output_filename = format!("{}/info{}.txt", bench_conf.args.path_output, bench_conf.benchmark_id); - let file = OpenOptions::new() - .append(true) - .create(true) - .open(&output_filename)?; - Some(file) - }; - let num: u64 = 1000; - let sys = System::new_all(); - if let Some(mut file) = memfile { - writeln!(file, "Benchmark done: {}", bench_conf.args.benchmark)?; - writeln!(file, "With queue: {}", queue)?; - - writeln!(file, "Arguments used in test:")?; - writeln!(file, "\n{}\n", bench_conf.args)?; - - writeln!(file, "Test ran on hardware specs:")?; - writeln!(file, "System name: {}", System::name().unwrap())?; - writeln!(file, "System kernel version: {}", System::kernel_version().unwrap())?; - writeln!(file, "System OS version: {}", System::os_version().unwrap())?; - writeln!(file, "Total RAM (in GB): {:?}", sys.total_memory()/(num.pow(3)))?; - - } - else { - eprintln!("Error producing info file") - } - Ok(()) -} - - -#[cfg(test)] -mod tests { - use crate::arguments::{EnqDeqArgs, EnqDeqPairsArgs}; - use crate::benchmarks::enq_deq_pairs::benchmark_enq_deq_pairs; - use crate::benchmarks::{ - prod_con::benchmark_prod_con, - enq_deq::benchmark_enq_deq - }; - - use super::*; - - /// A very simple ConcurrentQueue implementation for testing - mod test_queue { - use crate::traits::{ConcurrentQueue, Handle}; - use std::{collections::VecDeque, sync::Mutex}; - - pub struct TestQueue { - queue: Mutex>, - } - - pub struct TestQueueHandle<'a, T> { - queue: &'a TestQueue, - } - - impl Handle for TestQueueHandle<'_, T> { - fn push(&mut self, item: T) -> Result<(), T>{ - self.queue.queue.lock().unwrap().push_back(item); - Ok(()) - } - - fn pop(&mut self) -> Option { - self.queue.queue.lock().unwrap().pop_front() - } - } - - impl ConcurrentQueue for TestQueue { - fn register(&self) -> impl Handle { - TestQueueHandle { - queue: self, - } - } - - fn get_id(&self) -> String { - "test_queue".to_string() - } - - fn new(_size: usize) -> Self { - TestQueue { - queue: Mutex::new(VecDeque::new()) - } - } - } - } - use test_queue::TestQueue; - - #[test] - fn run_basic() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue: TestQueue = TestQueue::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_pingpong() { - let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_string() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_pingpong_with_bool() { - let args = Args { - benchmark: Benchmarks::EnqDeq(EnqDeqArgs { thread_count: 10, spread: 0.5 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_basic_with_struct() { - let args = Args::default(); - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test1".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_prod_con(queue, &bench_conf).is_err() { - panic!(); - } - } - - #[test] - fn run_enqdeq_pairs_with_struct() { - let args = Args { - benchmark: Benchmarks::EnqDeqPairs(EnqDeqPairsArgs { thread_count: 10 }), - ..Default::default() - }; - let bench_conf = BenchConfig { - args, - date_time: "".to_string(), - benchmark_id: "test2".to_string(), - output_filename: "".to_string() - }; - let queue = TestQueue::::new(0); - if benchmark_enq_deq_pairs(queue, &bench_conf).is_err() { - panic!(); - } - } -} +pub mod fifo_queue_benchmarks; +pub mod priority_queue_benchmarks; +pub mod benchmark_helpers; +pub(crate) mod test_helpers; diff --git a/benchmark_core/src/benchmarks/benchmark_helpers.rs b/benchmark_core/src/benchmarks/benchmark_helpers.rs new file mode 100644 index 0000000..1244ca1 --- /dev/null +++ b/benchmark_core/src/benchmarks/benchmark_helpers.rs @@ -0,0 +1,238 @@ +use crate::arguments::GeneralArgs; +#[cfg(feature = "memory_tracking")] +use crate::traits::ConcurrentQueue; +use chrono::Local; +#[cfg(feature = "memory_tracking")] +use jemalloc_ctl::{epoch, stats}; +use log::{debug, error, trace}; +use std::collections::hash_map::DefaultHasher; +use std::fs::OpenOptions; +use std::hash::{Hash, Hasher}; +use std::io::Write; +#[cfg(feature = "memory_tracking")] +use std::sync::atomic::AtomicBool; +use sysinfo::System; + +/// Benchmark config struct +/// Needs to be fully filled for benchmarks to be able to run. +pub struct BenchConfig { + pub args: GeneralArgs, + pub date_time: String, + pub benchmark_id: String, + pub output_filename: String, +} + +#[cfg(feature = "memory_tracking")] +pub fn create_mem_tracking_thread( + bench_conf: &BenchConfig, + _current_iteration: u32, + test_q: &Q, + _done: &std::sync::Arc, +) -> Result>, std::io::Error> +where + Q: ConcurrentQueue, +{ + use std::sync::atomic::Ordering; + // TODO: Check if core stuff is possible here as well. + // let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + // if *is_one_socket { + // core = core_iter.next().unwrap(); + // } + let _done = std::sync::Arc::clone(_done); + let benchmark_id = bench_conf.benchmark_id.clone(); + let bench_type = format!("{}", bench_conf.args.benchmark); + let to_stdout = bench_conf.args.write_to_stdout; + let queue_type = test_q.get_id(); + + // Create file if printing to stdout is disabled + let top_line = "Memory Allocated,Queuetype,Benchmark,Test ID,Iteration"; + let mut memfile = if !to_stdout { + let output_filename = format!( + "{}/mem{}", + bench_conf.args.path_output, bench_conf.date_time + ); + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&output_filename)?; + if _current_iteration == 0 { + writeln!(file, "{}", top_line)?; + } + Some(file) + } else { + if _current_iteration == 0 { + println!("{}", top_line); + } + None + }; + + // Spawn thread to check total memory allocated every 50ms + let interval = bench_conf.args.memory_tracking_interval; + debug!("Spawning memory thread."); + Ok(std::thread::spawn(move || -> Result<(), std::io::Error> { + while !_done.load(Ordering::Relaxed) { + // Update stats + if let Err(e) = epoch::advance() { + eprintln!("Error occured while advancing epoch: {}", e); + } + // Get allocated bytes + let allocated = stats::allocated::read().unwrap(); + + let output = format!( + "{},{},{},{},{}", + allocated, + queue_type, + bench_type, + &benchmark_id, + _current_iteration + ); + + match &mut memfile { + Some(file) => writeln!(file, "{}", output)?, + None => println!("{}", output), + } + + std::thread::sleep(std::time::Duration::from_millis(interval)); + } + Ok(()) + })) +} + +/// Calculates the fairness based on paper: +/// [A Study of the Behavior of Synchronization Methods in Commonly Used Languages and Systems](https://ieeexplore.ieee.org/document/6569906). +pub fn calc_fairness(ops_per_thread: Vec) -> f64 { + debug!("Calculating fairness"); + let sum: usize = ops_per_thread.iter().sum(); + + let length: f64 = ops_per_thread.len() as f64; + debug!("The vector {:?}", ops_per_thread); + debug!("Sum: {}, Length: {}", sum, length); + + // The thread that does the least amount of ops + let minop: f64 = match ops_per_thread.iter().min() { + Some(&val) => val as f64, + None => { + error!("No record of operations: {:?}", ops_per_thread); + panic!(); + } + }; + trace!("Minop fairness: {}", minop); + + // The thread that does the most amount of ops + let maxop: f64 = match ops_per_thread.iter().max() { + Some(&val) => val as f64, + None => { + error!("No record of operations: {:?}", ops_per_thread); + panic!(); + } + }; + trace!("Maxop fairness: {}", maxop); + + let fairness: f64 = + f64::min((length * minop) / sum as f64, sum as f64 / (length * maxop)); + + debug!("Calculated fairness: {}", fairness); + fairness +} + +/// Function to print the specifications of the hardware used and the benchmnark configs that ran +pub fn print_info( + queue: String, + bench_conf: &BenchConfig, + benchmark: String, +) -> Result<(), std::io::Error> { + // Create file if printing to stdout is disabled + if bench_conf.args.write_to_stdout { + return Ok(()); + } + let memfile = { + let output_filename = format!( + "{}/info{}.txt", + bench_conf.args.path_output, bench_conf.benchmark_id + ); + let file = OpenOptions::new() + .append(true) + .create(true) + .open(&output_filename)?; + Some(file) + }; + let num: u64 = 1000; + let sys = System::new_all(); + if let Some(mut file) = memfile { + writeln!(file, "Benchmark done: {}", benchmark)?; + writeln!(file, "With queue: {}", queue)?; + + writeln!(file, "Arguments used in test:")?; + writeln!(file, "\n{}\n", bench_conf.args)?; + + writeln!(file, "Test ran on hardware specs:")?; + writeln!(file, "System name: {}", System::name().unwrap())?; + writeln!( + file, + "System kernel version: {}", + System::kernel_version().unwrap() + )?; + writeln!( + file, + "System OS version: {}", + System::os_version().unwrap() + )?; + writeln!( + file, + "Total RAM (in GB): {:?}", + sys.total_memory() / (num.pow(3)) + )?; + } else { + eprintln!("Error producing info file") + } + Ok(()) +} + +pub fn create_bench_config( + general_args: &GeneralArgs, +) -> Result { + let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); + + // Create benchmark hashed id + let benchmark_id = { + let mut hasher = DefaultHasher::new(); + date_time.hash(&mut hasher); + format!("{:x}", hasher.finish()) + }; + + debug!("Benchmark ID: {}", benchmark_id); + debug!("Arguments: {:?}", general_args); + + // Create dir if it doesn't already exist. + if !std::path::Path::new(&general_args.path_output).exists() { + std::fs::create_dir(&general_args.path_output)?; + } + + let output_filename = format!("{}/{}", general_args.path_output, date_time); + + Ok(BenchConfig { + args: general_args.clone(), + date_time, + benchmark_id, + output_filename, + }) +} + +pub fn output_result_header( + output: String, + bench_config: &BenchConfig, +) -> Result<(), std::io::Error> { + if bench_config.args.write_to_stdout { + println!("{output}") + } else { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_config.output_filename)?; + writeln!(file, "{output}")?; + } + + Ok(()) +} diff --git a/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs new file mode 100644 index 0000000..126a01a --- /dev/null +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks.rs @@ -0,0 +1,136 @@ +#[allow(unused_imports)] +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks, GeneralArgs}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +#[allow(unused_imports)] +use crate::traits::{ConcurrentQueue, HandleQueue}; +use clap::Parser; +#[allow(unused_imports)] +use log::{self, debug, error, info}; +#[allow(unused_imports)] +use std::sync::atomic::AtomicBool; + +pub mod bfs; +pub mod enq_deq; +pub mod enq_deq_pairs; +pub mod prod_con; + +/// Create the fifo queue, and run the selected benchmark a set of times +pub fn benchmark_fifo_queue(queue_name: &str) -> Result<(), std::io::Error> +where + Q: ConcurrentQueue + Send, + for<'a> &'a Q: Send, +{ + let (bench_conf, fifo_queue_args) = setup_benchmark()?; + + // The variables need to be references to avoid moving into closures below. + // TODO(emilbjornlinger): Find a better solution. + let bench_conf = &bench_conf; + let fifo_queue_args = &fifo_queue_args; + + // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on + let mut runner: Box< + dyn FnMut(Q, &BenchConfig) -> Result<(), std::io::Error>, + > = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::ProdCon(_) => Box::new(move |q, bench_conf| { + prod_con::benchmark_prod_con(q, bench_conf, fifo_queue_args) + }), + FifoQueueBenchmarks::EnqDeq(_) => Box::new(move |q, bench_conf| { + enq_deq::benchmark_enq_deq(q, bench_conf, fifo_queue_args) + }), + FifoQueueBenchmarks::EnqDeqPairs(_) => { + Box::new(move |q, bench_conf| { + enq_deq_pairs::benchmark_enq_deq_pairs( + q, + bench_conf, + fifo_queue_args, + ) + }) + } + FifoQueueBenchmarks::BFS(args) => { + let (graph, seq_ret_vec, start_node) = bfs::pre_bfs_work( + Q::new(fifo_queue_args.queue_size as usize), + &args, + ); + Box::new(move |q, _conf| { + bfs::benchmark_bfs( + q, + &graph, + &bench_conf, + &seq_ret_vec, + start_node, + fifo_queue_args, + ) + }) + } + }; + + for _current_iteration in 0..bench_conf.args.iterations { + // Create the queue. + let test_q: Q = Q::new(fifo_queue_args.queue_size as usize); + + // Start memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + let (done, mem_thread_handle) = { + let done = + std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let handle = benchmark_helpers::create_mem_tracking_thread( + bench_conf, + _current_iteration, + &test_q, + &done, + )?; + (done, handle) + }; + + // Execute the benchmark + runner(test_q, &bench_conf)?; + + // Join the thread again + debug!("Queue should have been dropped now."); + + // Stop memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + { + use std::sync::atomic::Ordering; + debug!("Joining memory thread."); + done.store(true, Ordering::Relaxed); + if let Err(e) = mem_thread_handle.join().unwrap() { + log::error!("Couldn't join memory tracking thread: {}", e); + } + } + } + + if bench_conf.args.print_info { + benchmark_helpers::print_info( + queue_name.to_string(), + &bench_conf, + fifo_queue_args.benchmark_runner.to_string(), + )?; + } + + Ok(()) +} + +/// Parse arguments and start outputting result of benchmark +pub fn setup_benchmark() -> Result<(BenchConfig, FifoQueueArgs), std::io::Error> +{ + let args = crate::arguments::FifoQueueArgs::parse(); + let bench_config = + benchmark_helpers::create_bench_config(&args.general_args)?; + + let columns = match args.benchmark_runner { + FifoQueueBenchmarks::BFS(_) => { + "Milliseconds,Queuetype,Thread Count,Test ID" + }, + _ => { + "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" + } + }; + + benchmark_helpers::output_result_header( + columns.to_string(), + &bench_config, + )?; + + Ok((bench_config, args)) +} diff --git a/benchmark_core/src/benchmarks/bfs.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs similarity index 53% rename from benchmark_core/src/benchmarks/bfs.rs rename to benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs index fc16819..1ef41a8 100644 --- a/benchmark_core/src/benchmarks/bfs.rs +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/bfs.rs @@ -1,28 +1,35 @@ -use crate::{arguments::{BFSArgs, Benchmarks}, benchmarks::BenchConfig, traits::{ConcurrentQueue, Handle}}; -use std::{fs::OpenOptions, sync::{atomic::{AtomicUsize, Ordering}, Barrier}}; +use crate::arguments::{FifoQueueArgs, FifoQueueBFSArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::BenchConfig; +use crate::traits::{ConcurrentQueue, HandleQueue}; use core_affinity::CoreId; use log::{debug, error, info, trace}; use std::fs::File; use std::io::{BufRead, BufReader, Write}; - +use std::{ + fs::OpenOptions, + sync::{ + atomic::{AtomicUsize, Ordering}, + Barrier, + }, +}; /// Generates the graph, generates the sequential solution and gets which /// node to start at. -pub fn pre_bfs_work(cqueue: C, args: &BFSArgs) - -> (Vec>, Vec, usize) +pub fn pre_bfs_work( + cqueue: C, + args: &FifoQueueBFSArgs, +) -> (Vec>, Vec, usize) where -C: ConcurrentQueue, - for<'a> &'a C: Send + C: ConcurrentQueue, + for<'a> &'a C: Send, { info!("Loading graph now..."); - let graph = create_graph( - args.graph_file.clone(), - ).unwrap(); + let graph = create_graph(args.graph_file.clone()).unwrap(); // Find start node. Currently finds node with most neighbours. let mut biggest = 0; let mut curr = 0; for (i, edge) in graph.iter().enumerate() { - if edge.len() > biggest { + if edge.len() > biggest { biggest = edge.len(); curr = i; } @@ -54,31 +61,40 @@ dist_to_start_node /// /// Ex. run: /// cargo run -features data_structure,bfs -- bfs --graph-file graph.mtx -pub fn benchmark_bfs ( +pub fn benchmark_bfs( cqueue: C, graph: &[Vec], bench_conf: &BenchConfig, seq_ret_vec: &[usize], start_node: usize, - ) -> Result<(), std::io::Error> + fifo_queue_args: &FifoQueueArgs +) -> Result<(), std::io::Error> where -C: ConcurrentQueue, - for<'a> &'a C: Send + C: ConcurrentQueue, + for<'a> &'a C: Send, { - assert!(matches!(bench_conf.args.benchmark, Benchmarks::BFS(_))); - let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::BFS(a) => a, - _ => panic!(), + let bfs_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::BFS(a) => a, + _ => panic!( + "benchmark_bfs called with another FIFO Queue \ + configured. This is an implementation error." + ), }; - let thread_count = args.thread_count; + let thread_count = bfs_args.thread_count; debug!("Starting parallell BFS now"); - let (dur_par, par_ret_vec) = parallell_bfs(&cqueue, graph, start_node, thread_count, bench_conf); + let (dur_par, par_ret_vec) = + parallell_bfs(&cqueue, graph, start_node, thread_count, bench_conf); debug!("Graph traversal done. Took {:?}.", dur_par); - if !args.no_verify { + if !bfs_args.no_verify { debug!("Comparing results to the sequential solution"); for (i, node) in par_ret_vec.iter().enumerate() { - trace!("Pos: {} Parallell: {} Sequential: {}", i, *node, seq_ret_vec[i]); + trace!( + "Pos: {} Parallell: {} Sequential: {}", + i, + *node, + seq_ret_vec[i] + ); if *node != seq_ret_vec[i] { error!("Parallell BFS solution arrived at wrong answer."); return Ok(()); @@ -86,19 +102,20 @@ C: ConcurrentQueue, } debug!("Solution looks good."); } - let formatted = format!("{},{},{},{}", - dur_par.as_millis(), - cqueue.get_id(), - args.thread_count, - bench_conf.benchmark_id); + let formatted = format!( + "{},{},{},{}", + dur_par.as_millis(), + cqueue.get_id(), + bfs_args.thread_count, + bench_conf.benchmark_id + ); if !bench_conf.args.write_to_stdout { let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; writeln!(file, "{}", formatted)?; - } else { println!("{}", formatted); } @@ -106,20 +123,20 @@ C: ConcurrentQueue, Ok(()) } -fn parallell_bfs ( +fn parallell_bfs( cqueue: &C, graph: &[Vec], start_node: usize, thread_count: usize, - bench_conf: &BenchConfig) --> (std::time::Duration, Vec) + bench_conf: &BenchConfig, +) -> (std::time::Duration, Vec) where -C: ConcurrentQueue, - for<'a> &'a C: Send + C: ConcurrentQueue, + for<'a> &'a C: Send, { - - let result_vector: Vec = - (0..graph.len()).map(|_| AtomicUsize::new(usize::MAX)).collect(); + let result_vector: Vec = (0..graph.len()) + .map(|_| AtomicUsize::new(usize::MAX)) + .collect(); // Set distance of first node result_vector[start_node].store(0, Ordering::Relaxed); @@ -135,48 +152,49 @@ C: ConcurrentQueue, core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); let mut core_iter = available_cores.into_iter().cycle(); - let scope_result = std::thread::scope(|s| -> Result{ - let idle_count = &idle_count; - let no_work_count = &no_work_count; - let barrier = &barrier; - let result_vector = &result_vector; - let mut handles = vec![]; - let is_one_socket = &bench_conf.args.one_socket; - for i in 0..thread_count { - handles.push({ - let mut core : CoreId = core_iter.next().unwrap(); - // if is_one_socket is true, make all thread ids even - // (this was used for our testing enviroment to get one socket) - if *is_one_socket { - core = core_iter.next().unwrap(); - } - s.spawn(move|| { - core_affinity::set_for_current(core); - // Register queue - let handle = cqueue.register(); - // Wait for other queues - barrier.wait(); - // Start BFS - pbfs_helper( - handle, - result_vector, - graph, - i, - no_work_count, - idle_count, - thread_count - ); - }) - }); - } - barrier.wait(); - let start = std::time::Instant::now(); - for handle in handles { - handle.join().unwrap(); - } - let duration = start.elapsed(); - Ok(duration) - }); + let scope_result = + std::thread::scope(|s| -> Result { + let idle_count = &idle_count; + let no_work_count = &no_work_count; + let barrier = &barrier; + let result_vector = &result_vector; + let mut handles = vec![]; + let is_one_socket = &bench_conf.args.one_socket; + for i in 0..thread_count { + handles.push({ + let mut core: CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + s.spawn(move || { + core_affinity::set_for_current(core); + // Register queue + let handle = cqueue.register(); + // Wait for other queues + barrier.wait(); + // Start BFS + pbfs_helper( + handle, + result_vector, + graph, + i, + no_work_count, + idle_count, + thread_count, + ); + }) + }); + } + barrier.wait(); + let start = std::time::Instant::now(); + for handle in handles { + handle.join().unwrap(); + } + let duration = start.elapsed(); + Ok(duration) + }); let duration = scope_result.expect("Should never return error"); let ret_vec: Vec = result_vector .iter() @@ -187,14 +205,14 @@ C: ConcurrentQueue, } fn pbfs_helper( - mut handle: impl Handle, + mut handle: impl HandleQueue, result_vector: &[AtomicUsize], graph: &[Vec], i: usize, no_work_count: &AtomicUsize, idle_count: &AtomicUsize, - thread_count: usize) -{ + thread_count: usize, +) { let mut next = None; loop { if next.is_none() { @@ -206,38 +224,51 @@ fn pbfs_helper( trace!("Thread: {i}; Acquired node {node}"); let distance = result_vector[node].load(Ordering::SeqCst); for neighbour in &graph[node] { - let mut n_distance = result_vector[*neighbour].load(Ordering::SeqCst); + let mut n_distance = + result_vector[*neighbour].load(Ordering::SeqCst); while distance + 1 < n_distance { - if result_vector[*neighbour].compare_exchange_weak( - n_distance, - distance + 1, - Ordering::SeqCst, - Ordering::SeqCst) + if result_vector[*neighbour] + .compare_exchange_weak( + n_distance, + distance + 1, + Ordering::SeqCst, + Ordering::SeqCst, + ) .is_ok() { match handle.push(*neighbour) { Err(e) => { error!("Failed to push to queue: {e}"); continue; - }, + } Ok(_) => { - trace!("Thread: {i}; Pushed {}", *neighbour); + trace!( + "Thread: {i}; Pushed {}", + *neighbour + ); break; - }, + } } } - n_distance = result_vector[*neighbour].load(Ordering::SeqCst); + n_distance = + result_vector[*neighbour].load(Ordering::SeqCst); } } - }, + } None => { trace!("Thread: {i}; Did not acquire any work"); no_work_count.fetch_add(1, Ordering::Relaxed); loop { next = handle.pop(); - if next.is_some() { break; } + if next.is_some() { + break; + } if no_work_count.load(Ordering::Relaxed) >= thread_count - && should_terminate(idle_count, no_work_count, thread_count) + && should_terminate( + idle_count, + no_work_count, + thread_count, + ) { return; } @@ -248,7 +279,11 @@ fn pbfs_helper( } } -fn should_terminate(idle_count: &AtomicUsize, no_work_count: &AtomicUsize, thread_count: usize) -> bool { +fn should_terminate( + idle_count: &AtomicUsize, + no_work_count: &AtomicUsize, + thread_count: usize, +) -> bool { idle_count.fetch_add(1, Ordering::Relaxed); while no_work_count.load(Ordering::Relaxed) >= thread_count { if idle_count.load(Ordering::Relaxed) >= thread_count { @@ -261,13 +296,19 @@ fn should_terminate(idle_count: &AtomicUsize, no_work_count: &AtomicUsize, threa false } -fn sequential_bfs(cqueue: C, graph: &[Vec], start_node: usize) -> Vec +fn sequential_bfs( + cqueue: C, + graph: &[Vec], + start_node: usize, +) -> Vec where -C: ConcurrentQueue, - for<'a> &'a C: Send + C: ConcurrentQueue, + for<'a> &'a C: Send, { - let mut result_vector: Vec = (0..graph.len()).map(|_| usize::MAX).collect(); - let mut visited: std::collections::HashSet = std::collections::HashSet::new(); + let mut result_vector: Vec = + (0..graph.len()).map(|_| usize::MAX).collect(); + let mut visited: std::collections::HashSet = + std::collections::HashSet::new(); let mut q = cqueue.register(); result_vector[start_node] = 0; if q.push(start_node).is_err() { @@ -293,7 +334,9 @@ C: ConcurrentQueue, result_vector } -pub fn create_graph(graph_file: String) -> Result>, std::io::Error> { +pub fn create_graph( + graph_file: String, +) -> Result>, std::io::Error> { let file = File::open(graph_file)?; let reader = BufReader::new(file); @@ -304,8 +347,12 @@ pub fn create_graph(graph_file: String) -> Result>, std::io::Erro continue; } - let edge: Vec = line.split(' ') - .map(|n| n.parse::().expect("File populated with non-integers")) + let edge: Vec = line + .split(' ') + .map(|n| { + n.parse::() + .expect("File populated with non-integers") + }) .collect(); edges.push(edge); @@ -323,4 +370,3 @@ pub fn create_graph(graph_file: String) -> Result>, std::io::Erro Ok(graph) } // Milliseconds,Queuetype,Thread Count,Test ID - diff --git a/benchmark_core/src/benchmarks/enq_deq.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs similarity index 65% rename from benchmark_core/src/benchmarks/enq_deq.rs rename to benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs index c244889..c60e90f 100644 --- a/benchmark_core/src/benchmarks/enq_deq.rs +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq.rs @@ -1,10 +1,12 @@ +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::{calc_fairness, BenchConfig}}; use std::fs::OpenOptions; use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; use std::sync::{mpsc, Arc}; /// # Explanation: @@ -14,24 +16,33 @@ use std::sync::{mpsc, Arc}; /// * --spread Set the spread of consumers/producers, value between 0 - 1. Ex. --spread 0.3, gives 30% consume, 70% produce /// * --thread-count Set the amount of threads to run in the benchmark #[allow(dead_code)] -pub fn benchmark_enq_deq (cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_enq_deq ( + cqueue: C, + bench_conf: &BenchConfig, + fifo_queue_args: &FifoQueueArgs, +) -> Result<(), std::io::Error> where C: ConcurrentQueue, T: Default, for<'a> &'a C: Send { - let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::EnqDeq(a) => a, - _ => panic!(), + // Extract specific arguments for this benchmark runner + let enq_deq_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::EnqDeq(a) => a, + _ => panic!( + "benchmark_enq_deq called with another FIFO Queue \ + configured. This is an implementation error." + ), }; + { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); + debug!("Prefilling queue with {} items.", fifo_queue_args.prefill_amount); let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { + for _ in 0..fifo_queue_args.prefill_amount { let _ = tmp_handle.push(Default::default()); } } - let thread_count = args.thread_count; + let thread_count = enq_deq_args.thread_count; let time_limit: u64 = bench_conf.args.time_limit; let barrier = Barrier::new(thread_count + 1); let pops = AtomicUsize::new(0); @@ -59,7 +70,7 @@ T: Default, let done = &done; let barrier = &barrier; let &thread_count = &thread_count; - let &spread = &args.spread; + let &spread = &enq_deq_args.spread; let is_one_socket = &bench_conf.args.one_socket; let tx = &tx; for _i in 0..thread_count{ @@ -84,7 +95,7 @@ T: Default, match handle.pop() { Some(_) => l_pops += 1, None => { - if bench_conf.args.empty_pops { + if fifo_queue_args.empty_pops { l_pops += 1; } } @@ -128,17 +139,17 @@ T: Default, } vals }; - let fairness = calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { format!("0,0,0,-1,-1,{},{},{},{},0,{},{}", thread_count, cqueue.get_id(), - bench_conf.args.benchmark, + fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, - args.spread, - bench_conf.args.queue_size + enq_deq_args.spread, + fifo_queue_args.queue_size ) } else { @@ -150,11 +161,12 @@ T: Default, -1, thread_count, cqueue.get_id(), - bench_conf.args.benchmark, + fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, fairness, - args.spread, - bench_conf.args.queue_size) + enq_deq_args.spread, + fifo_queue_args.queue_size + ) }; // Write to file or stdout depending on flag if !bench_conf.args.write_to_stdout { @@ -168,3 +180,58 @@ T: Default, } Ok(()) } + +#[cfg(test)] +mod tests { + use crate::arguments::FifoQueueArgs; + use crate::arguments::FifoQueueBenchmarks; + use crate::arguments::FifoQueueEnqDeqArgs; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_pingpong() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeq( + FifoQueueEnqDeqArgs { thread_count: 10 , spread: 0.5 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } + + #[test] + fn run_pingpong_with_bool() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeq( + FifoQueueEnqDeqArgs { thread_count: 10 , spread: 0.5 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/enq_deq_pairs.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs similarity index 59% rename from benchmark_core/src/benchmarks/enq_deq_pairs.rs rename to benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs index 18938a5..14b79ee 100644 --- a/benchmark_core/src/benchmarks/enq_deq_pairs.rs +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/enq_deq_pairs.rs @@ -1,42 +1,59 @@ +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use crate::traits::{ConcurrentQueue, HandleQueue}; use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::{calc_fairness, BenchConfig}}; use std::fs::OpenOptions; use std::io::Write; +use std::sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Barrier, +}; use std::sync::{mpsc, Arc}; /// # Explanation: #[allow(dead_code)] -pub fn benchmark_enq_deq_pairs (cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_enq_deq_pairs( + cqueue: C, + bench_conf: &BenchConfig, + fifo_queue_args: &FifoQueueArgs, +) -> Result<(), std::io::Error> where -C: ConcurrentQueue, -T: Default, - for<'a> &'a C: Send + C: ConcurrentQueue, + T: Default, + for<'a> &'a C: Send, { - let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::EnqDeqPairs(a) => a, - _ => panic!(), + // Extract specific arguments for this benchmark runner + let enq_deq_pairs_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::EnqDeqPairs(a) => a, + _ => panic!( + "benchmark_enq_deq_pairs called with another FIFO Queue \ + configured. This is an implementation error." + ), }; + { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); + debug!( + "Prefilling queue with {} items.", + fifo_queue_args.prefill_amount + ); + let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { + for _ in 0..fifo_queue_args.prefill_amount { let _ = tmp_handle.push(Default::default()); } } - let thread_count = args.thread_count; + + let thread_count = enq_deq_pairs_args.thread_count; let time_limit: u64 = bench_conf.args.time_limit; let barrier = Barrier::new(thread_count + 1); - let pops = AtomicUsize::new(0); + let pops = AtomicUsize::new(0); let pushes = AtomicUsize::new(0); let done = AtomicBool::new(false); let (tx, rx) = mpsc::channel(); info!("Starting pingpong benchmark with {} threads", thread_count); - - // Get cores for fairness of threads let available_cores: Vec = core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); @@ -45,8 +62,7 @@ T: Default, // Shared atomic bool for when a thread fails let thread_failed = Arc::new(AtomicBool::new(false)); - - let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ + let _ = std::thread::scope(|s| -> Result<(), std::io::Error> { let queue = &cqueue; let thread_failed = &thread_failed; // Every thread clones the thread_failed bool let pushes = &pushes; @@ -56,8 +72,8 @@ T: Default, let &thread_count = &thread_count; let is_one_socket = &bench_conf.args.one_socket; let tx = &tx; - for _i in 0..thread_count{ - let mut core : CoreId = core_iter.next().unwrap(); + for _i in 0..thread_count { + let mut core: CoreId = core_iter.next().unwrap(); // if is_one_socket is true, make all thread ids even // (this was used for our testing enviroment to get one socket) if *is_one_socket { @@ -93,7 +109,6 @@ T: Default, done.store(true, Ordering::Relaxed); } }); - } barrier.wait(); std::thread::sleep(std::time::Duration::from_secs(time_limit)); @@ -111,33 +126,35 @@ T: Default, } vals }; - let fairness = calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,-1,-1,{},{},{},{},0,{},{}", + format!( + "0,0,0,-1,-1,{},{},{},{},0,{},{}", thread_count, cqueue.get_id(), - bench_conf.args.benchmark, + fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, -1, - bench_conf.args.queue_size - ) - } - else { - format!("{},{},{},{},{},{},{},{},{},{},{},{}", - (pushes + pops) as f64 / time_limit as f64, - pushes, - pops, - -1, - -1, - thread_count, - cqueue.get_id(), - bench_conf.args.benchmark, - bench_conf.benchmark_id, - fairness, - -1, - bench_conf.args.queue_size) + fifo_queue_args.queue_size + ) + } else { + format!( + "{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + -1, + -1, + thread_count, + cqueue.get_id(), + fifo_queue_args.benchmark_runner, + bench_conf.benchmark_id, + fairness, + -1, + fifo_queue_args.queue_size + ) }; // Write to file or stdout depending on flag if !bench_conf.args.write_to_stdout { @@ -151,3 +168,36 @@ T: Default, } Ok(()) } + +#[cfg(test)] +mod tests { + use crate::arguments::FifoQueueArgs; + use crate::arguments::FifoQueueBenchmarks; + use crate::arguments::FifoQueueEnqDeqPairsArgs; + + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_enqdeq_pairs_with_struct() { + let fifo_queue_args = FifoQueueArgs { + benchmark_runner: FifoQueueBenchmarks::EnqDeqPairs( + FifoQueueEnqDeqPairsArgs { thread_count: 20 }, + ), + ..Default::default() + }; + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test2".to_string(), + output_filename: "".to_string(), + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_enq_deq_pairs(queue, &bench_conf, &fifo_queue_args) + .is_err() + { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs similarity index 73% rename from benchmark_core/src/benchmarks/prod_con.rs rename to benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs index 96ae4b5..b1e1b09 100644 --- a/benchmark_core/src/benchmarks/prod_con.rs +++ b/benchmark_core/src/benchmarks/fifo_queue_benchmarks/prod_con.rs @@ -1,10 +1,12 @@ use core_affinity::CoreId; use log::{debug, error, info, trace}; use rand::Rng; -use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; -use crate::{traits::{ConcurrentQueue, Handle}, benchmarks::BenchConfig}; +use crate::arguments::{FifoQueueArgs, FifoQueueBenchmarks}; +use crate::traits::{ConcurrentQueue, HandleQueue}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; use std::fs::OpenOptions; use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; use std::sync::{mpsc, Arc}; /// # Explanation: @@ -15,25 +17,28 @@ use std::sync::{mpsc, Arc}; /// * -p Set specified amount of producers /// * -c Set specified amount of consumers #[allow(dead_code)] -pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig) -> Result<(), std::io::Error> +pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig, fifo_queue_args: &FifoQueueArgs) -> Result<(), std::io::Error> where C: ConcurrentQueue, T: Default, for<'a> &'a C: Send { - let args = match &bench_conf.args.benchmark { - crate::arguments::Benchmarks::ProdCon(a) => a, - _ => panic!(), + // Extract specific arguments for this benchmark runner + let prod_con_args = match &fifo_queue_args.benchmark_runner { + FifoQueueBenchmarks::ProdCon(a) => a, + _ => panic!("benchmark_prod_con called with another FIFO Queue \ + configured. This is an implementation error.") }; + { - debug!("Prefilling queue with {} items.", bench_conf.args.prefill_amount); + debug!("Prefilling queue with {} items.", fifo_queue_args.prefill_amount); let mut tmp_handle = cqueue.register(); - for _ in 0..bench_conf.args.prefill_amount { + for _ in 0..fifo_queue_args.prefill_amount { let _ = tmp_handle.push(Default::default()); } } - let producers = args.producers; - let consumers = args.consumers; + let producers = prod_con_args.producers; + let consumers = prod_con_args.consumers; let time_limit: u64 = bench_conf.args.time_limit; let barrier = Barrier::new(consumers + producers + 1); @@ -172,10 +177,10 @@ where }; // If a thread crashed, pad the results with zero-values let formatted = if thread_failed.load(Ordering::Relaxed) { - format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), bench_conf.args.benchmark, bench_conf.benchmark_id, bench_conf.args.queue_size) + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, fifo_queue_args.queue_size) } else { - let fairness = crate::benchmarks::calc_fairness(ops_per_thread); + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); format!("{},{},{},{},{},{},{},{},{},{},{},{}", (pushes + pops) as f64 / time_limit as f64, pushes, @@ -184,11 +189,11 @@ where producers, -1, cqueue.get_id(), - bench_conf.args.benchmark, + fifo_queue_args.benchmark_runner, bench_conf.benchmark_id, fairness, -1, - bench_conf.args.queue_size) + fifo_queue_args.queue_size) }; if !bench_conf.args.write_to_stdout { let mut file = OpenOptions::new() @@ -206,3 +211,54 @@ where } +#[cfg(test)] +mod tests { + use super::*; + + use crate::benchmarks::test_helpers::test_queue::TestQueue; + + #[test] + fn run_basic_prod_con() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_string() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_struct() { + let fifo_queue_args = FifoQueueArgs::default(); + let bench_conf = benchmark_helpers::BenchConfig { + args: fifo_queue_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestQueue = TestQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &fifo_queue_args).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs new file mode 100644 index 0000000..3eac921 --- /dev/null +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks.rs @@ -0,0 +1,109 @@ +#[allow(unused_imports)] +use crate::arguments::{ + GeneralArgs, PriorityQueueArgs, PriorityQueueBenchmarks, +}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +#[allow(unused_imports)] +use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use clap::Parser; +#[allow(unused_imports)] +use log::{self, debug, error, info}; +#[allow(unused_imports)] +use std::sync::atomic::AtomicBool; + +pub mod prod_con; + +/// Create the queue, and run the selected benchmark a set of times +pub fn benchmark_priority_queue( + queue_name: &str, +) -> Result<(), std::io::Error> +where + Q: ConcurrentPriorityQueue + Send, + T: Default, + for<'a> &'a Q: Send, +{ + let (bench_conf, pq_args) = setup_benchmark()?; + + // The variables need to be references to avoid moving into closures below. + // TODO(emilbjornlinger): Find a better solution. + let bench_conf = &bench_conf; + let pq_args = &pq_args; + + // Create a runner lambda for the different benchmarks, mainly needed for eg. BFS to load graph and so on + let mut runner: Box< + dyn FnMut( + Q, + &benchmark_helpers::BenchConfig, + ) -> Result<(), std::io::Error>, + > = match &pq_args.benchmark_runner { + PriorityQueueBenchmarks::ProdCon(_) => { + Box::new(move |q, bench_conf| { + prod_con::benchmark_prod_con(q, bench_conf, pq_args) + }) + } + }; + + for _current_iteration in 0..bench_conf.args.iterations { + // Create the queue. + let test_q: Q = Q::new(pq_args.queue_size as usize); + + // Start memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + let (done, mem_thread_handle) = { + let done = + std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)); + let handle = benchmark_helpers::create_mem_tracking_thread( + bench_conf, + _current_iteration, + &test_q, + &done, + )?; + (done, handle) + }; + + // Execute the benchmark + runner(test_q, bench_conf)?; + + // Join the thread again + debug!("Queue should have been dropped now."); + + // Stop memory tracking (if enabled) + #[cfg(feature = "memory_tracking")] + { + use std::sync::atomic::Ordering; + debug!("Joining memory thread."); + done.store(true, Ordering::Relaxed); + if let Err(e) = mem_thread_handle.join().unwrap() { + log::error!("Couldn't join memory tracking thread: {}", e); + } + } + } + + if bench_conf.args.print_info { + benchmark_helpers::print_info( + queue_name.to_string(), + bench_conf, + pq_args.benchmark_runner.to_string(), + )?; + } + + Ok(()) +} + +/// Parse arguments and start outputting result of benchmark +pub fn setup_benchmark( +) -> Result<(BenchConfig, PriorityQueueArgs), std::io::Error> { + let args = crate::arguments::PriorityQueueArgs::parse(); + let bench_config = + benchmark_helpers::create_bench_config(&args.general_args)?; + + let columns = "Throughput,Enqueues,Dequeues,Consumers,Producers,\ + Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size"; + + benchmark_helpers::output_result_header( + columns.to_string(), + &bench_config, + )?; + + Ok((bench_config, args)) +} diff --git a/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs new file mode 100644 index 0000000..0f35975 --- /dev/null +++ b/benchmark_core/src/benchmarks/priority_queue_benchmarks/prod_con.rs @@ -0,0 +1,267 @@ +use core_affinity::CoreId; +use log::{debug, error, info, trace}; +use rand::Rng; +use crate::arguments::{PriorityQueueArgs, PriorityQueueBenchmarks}; +use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use crate::benchmarks::benchmark_helpers::{self, BenchConfig}; +use std::fs::OpenOptions; +use std::io::Write; +use std::sync::{atomic::{AtomicBool, AtomicUsize, Ordering}, Barrier}; +use std::sync::{mpsc, Arc}; + +// TODO(emilbjornlinger): Change benchmark to something reasonable + +/// # Explanation: +/// A simple benchmark that measures the throughput of a queue. +/// Has by default a 10 floating points generated delay between each operation, but this can be changed +/// through flags passed to the program. +/// Benchmark specific flags: +/// * -p Set specified amount of producers +/// * -c Set specified amount of consumers +#[allow(dead_code)] +pub fn benchmark_prod_con(cqueue: C, bench_conf: &BenchConfig, pq_args: &PriorityQueueArgs) -> Result<(), std::io::Error> +where + C: ConcurrentPriorityQueue, + P: Ord + From, + T: Default, + for<'a> &'a C: Send +{ + // Extract specific arguments for this benchmark runner + let prod_con_args = match &pq_args.benchmark_runner { + PriorityQueueBenchmarks::ProdCon(a) => a, + }; + + { + debug!("Prefilling priority queue with {} items.", pq_args.prefill_amount); + let mut tmp_handle = cqueue.register(); + for i in 0..pq_args.prefill_amount { + let prio: usize = i.try_into().unwrap(); + let _ = tmp_handle.insert(P::from(prio), Default::default()); + } + } + let producers = prod_con_args.producers; + let consumers = prod_con_args.consumers; + + let time_limit: u64 = bench_conf.args.time_limit; + let barrier = Barrier::new(consumers + producers + 1); + let pops = AtomicUsize::new(0); + let pushes = AtomicUsize::new(0); + let done = AtomicBool::new(false); + let (tx, rx) = mpsc::channel(); + info!("Starting throughput benchmark with {} consumer and {} producers", consumers, producers); + + // get cores for fairness of threads + let available_cores: Vec = + core_affinity::get_core_ids().unwrap_or(vec![CoreId { id: 0 }]); + let mut core_iter = available_cores.into_iter().cycle(); + + // Shared atomic bool for when a thread fails + let thread_failed = Arc::new(AtomicBool::new(false)); + + let _ = std::thread::scope(|s| -> Result<(), std::io::Error>{ + let queue = &cqueue; + let pushes = &pushes; + let pops = &pops; + let done = &done; + let barrier = &barrier; + let tx = &tx; + let &consumers = &consumers; + let &producers = &producers; + let is_one_socket = &bench_conf.args.one_socket; + let thread_failed = &thread_failed; + + for i in 0..producers{ + let mut core : CoreId = core_iter.next().unwrap(); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // push + let mut l_pushes= 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + while !done.load(Ordering::Relaxed) { + // NOTE: Maybe we should care about this result? + let _ = handle.insert(P::from(l_pushes), T::default()); + l_pushes += 1; + // Add some delay to simulate real workload + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pushes.fetch_add(l_pushes, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pushes) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err (e) = result { + error!("Thread {} panicked in pushing: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + for i in 0..consumers { + let mut core : CoreId = core_iter.next().expect("Core iter error"); + // if is_one_socket is true, make all thread ids even + // (this was used for our testing enviroment to get one socket) + if *is_one_socket { + core = core_iter.next().unwrap(); + } + trace!("Thread: {} Core: {:?}", i, core); + + s.spawn(move || { + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + core_affinity::set_for_current(core); + let mut handle = queue.register(); + // pop + let mut l_pops = 0; + let mut empty_pops = 0; + let _thread_failed = thread_failed.clone(); // Every thread clones the thread_failed bool + barrier.wait(); + // TODO: add empty pops probably to fairness calculations + while !done.load(Ordering::Relaxed) { + match handle.delete_min() { + Some(_) => l_pops += 1, + None => { + // if bench_conf.args.empty_pops { + // l_pops += 1; + // } + empty_pops += 1; + } + } + for _ in 0..bench_conf.args.delay { + let _some_num = rand::rng().random::(); + } + } + pops.fetch_add(l_pops, Ordering::Relaxed); + // Thread sends its total operations down the channel for fairness calculations + if let Err(e) = tx.send(l_pops + empty_pops) { + error!("Error sending operations down the channel: {}", e); + }; + })); + // A thread panicked, aborting the benchmark... + if let Err(e) = result { + error!("Thread {} panicked while popping: {:?}. Aborting benchmark, padding results to zero", i, e); + thread_failed.store(true, Ordering::Relaxed); + done.store(true, Ordering::Relaxed); + } + }); + } + debug!("Waiting for barrier"); + barrier.wait(); + debug!("Done waiting for barrier. Going to sleep."); + std::thread::sleep(std::time::Duration::from_secs(time_limit)); + done.store(true, Ordering::Relaxed); + Ok(()) + }); + drop(tx); + debug!("TX Dropped"); + let pops = pops.into_inner(); + let pushes = pushes.into_inner(); + + // Fairness + // Get total operations per thread + let ops_per_thread = { + let mut vals = vec![]; + for received in rx { + vals.push(received); + }; + vals + }; + // If a thread crashed, pad the results with zero-values + let formatted = if thread_failed.load(Ordering::Relaxed) { + format!("0,0,0,{},{},-1,{},{},{},0,-1,{}", producers, consumers, cqueue.get_id(), pq_args.benchmark_runner, bench_conf.benchmark_id, pq_args.queue_size) + } + else { + let fairness = benchmark_helpers::calc_fairness(ops_per_thread); + format!("{},{},{},{},{},{},{},{},{},{},{},{}", + (pushes + pops) as f64 / time_limit as f64, + pushes, + pops, + consumers, + producers, + -1, + cqueue.get_id(), + pq_args.benchmark_runner, + bench_conf.benchmark_id, + fairness, + -1, + pq_args.queue_size) + }; + if !bench_conf.args.write_to_stdout { + let mut file = OpenOptions::new() + .append(true) + .create(true) + .open(&bench_conf.output_filename)?; + + writeln!(file, "{}", formatted)?; + + } else { + println!("{}", formatted); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::arguments::PriorityQueueArgs; + + use crate::benchmarks::test_helpers::test_priority_queue::TestPriorityQueue; + + #[test] + fn run_basic_prod_con() { + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_string() { + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { + panic!(); + } + } + + #[test] + fn run_basic_with_struct() { + let pq_args = PriorityQueueArgs::default(); + let bench_conf = BenchConfig { + args: pq_args.general_args.clone(), + date_time: "".to_string(), + benchmark_id: "test1".to_string(), + output_filename: "".to_string() + }; + let queue: TestPriorityQueue = TestPriorityQueue::new(0); + if benchmark_prod_con(queue, &bench_conf, &pq_args).is_err() { + panic!(); + } + } +} diff --git a/benchmark_core/src/benchmarks/test_helpers.rs b/benchmark_core/src/benchmarks/test_helpers.rs new file mode 100644 index 0000000..07de017 --- /dev/null +++ b/benchmark_core/src/benchmarks/test_helpers.rs @@ -0,0 +1,128 @@ +/// A simple ConcurrentQueue implementation for testing +#[cfg(test)] +pub(crate) mod test_queue { + use crate::traits::{ConcurrentQueue, HandleQueue}; + use std::collections::VecDeque; + use std::sync::Mutex; + + pub struct TestQueue { + queue: Mutex>, + } + + pub struct TestQueueHandle<'a, T> { + queue: &'a TestQueue, + } + + impl HandleQueue for TestQueueHandle<'_, T> { + fn push(&mut self, item: T) -> Result<(), T> { + self.queue.queue.lock().unwrap().push_back(item); + Ok(()) + } + + fn pop(&mut self) -> Option { + self.queue.queue.lock().unwrap().pop_front() + } + } + + impl ConcurrentQueue for TestQueue { + fn register(&self) -> impl HandleQueue { + TestQueueHandle { queue: self } + } + + fn get_id(&self) -> String { + "test_queue".to_string() + } + + fn new(_size: usize) -> Self { + TestQueue { + queue: Mutex::new(VecDeque::new()), + } + } + } +} + +/// A very simple ConcurrentPriorityQueue implementation for testing +#[cfg(test)] +pub(crate) mod test_priority_queue { + use crate::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; + use std::cmp::{Ordering, Reverse}; + use std::collections::BinaryHeap; + use std::sync::Mutex; + + pub struct KeyValuePair { + key: Reverse

, + item: T, + } + + impl KeyValuePair { + pub fn new(key: P, item: T) -> Self { + Self { + key: Reverse(key), + item, + } + } + } + + impl Ord for KeyValuePair { + fn cmp(&self, other: &Self) -> Ordering { + self.key.cmp(&other.key) + } + } + + impl PartialOrd for KeyValuePair { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + impl PartialEq for KeyValuePair { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } + } + + impl Eq for KeyValuePair {} + + pub struct TestPriorityQueue { + queue: Mutex>>, + } + + pub struct TestPriorityQueueHandle<'a, P: Ord, T> { + queue: &'a TestPriorityQueue, + } + + impl HandlePriorityQueue + for TestPriorityQueueHandle<'_, P, T> + { + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { + let kv_pair = KeyValuePair::new(priority, item); + self.queue.queue.lock().unwrap().push(kv_pair); + Ok(()) + } + fn delete_min(&mut self) -> Option { + match self.queue.queue.lock().unwrap().pop() { + Some(kv_pair) => Some(kv_pair.item), + None => None, + } + } + fn is_empty(&mut self) -> bool { + self.queue.queue.lock().unwrap().is_empty() + } + } + + impl ConcurrentPriorityQueue for TestPriorityQueue { + fn register(&self) -> impl HandlePriorityQueue { + TestPriorityQueueHandle { queue: self } + } + + fn get_id(&self) -> String { + "test_queue".to_string() + } + + fn new(_size: usize) -> Self { + TestPriorityQueue { + queue: Mutex::new(BinaryHeap::new()), + } + } + } +} diff --git a/benchmark_core/src/lib.rs b/benchmark_core/src/lib.rs index 3c16748..d00b13c 100644 --- a/benchmark_core/src/lib.rs +++ b/benchmark_core/src/lib.rs @@ -5,85 +5,7 @@ use jemallocator::Jemalloc; #[global_allocator] static GLOBAL: Jemalloc = Jemalloc; -use chrono::Local; -#[allow(unused_imports)] -use log::{self, debug, error, info}; -use clap::Parser; -use std::collections::hash_map::DefaultHasher; -use std::fs::OpenOptions; -use std::hash::{Hash, Hasher}; -use std::io::Write; -#[allow(unused_imports)] -use crate::traits::{ConcurrentQueue, Handle}; - pub mod benchmarks; pub mod order; pub mod arguments; pub mod traits; - - -pub struct SetupResult { - pub bench_conf: benchmarks::BenchConfig, - pub columns: String, // Optional, but alreadyy written (TODO: have a stream of some sort here) -} - -pub fn benchmark_target_queue(queue_name: &str) -> Result<(), std::io::Error> -where - Q: ConcurrentQueue + Send, - for<'a> &'a Q: Send -{ - let SetupResult { bench_conf, .. } = setup_benchmark()?; - benchmarks::benchmark_queue::(&bench_conf, queue_name) -} - - -/// Set up the actual benchmark. -/// -/// All work unrelated to the chosen benchmark is done here. -pub fn setup_benchmark() -> Result { - let args = crate::arguments::Args::parse(); - let date_time = Local::now().format("%Y%m%d%H%M%S").to_string(); - // Create benchmark hashed id - let benchmark_id = { - let mut hasher = DefaultHasher::new(); - date_time.hash(&mut hasher); - format!("{:x}", hasher.finish()) - }; - - debug!("Benchmark ID: {}", benchmark_id); - debug!("Arguments: {:?}", args); - - // Create dir if it doesnt already exist. - if !std::path::Path::new(&args.path_output).exists() { - std::fs::create_dir(&args.path_output)?; - } - - let output_filename = format!("{}/{}", args.path_output, date_time); - let bench_conf = benchmarks::BenchConfig { - args, - date_time, - benchmark_id, - output_filename, - }; - - let columns = match bench_conf.args.benchmark { - arguments::Benchmarks::BFS(_) => { - "Milliseconds,Queuetype,Thread Count,Test ID" - }, - _ => { - "Throughput,Enqueues,Dequeues,Consumers,Producers,Thread Count,Queuetype,Benchmark,Test ID,Fairness,Spread,Queue Size" - } - }; - - if bench_conf.args.write_to_stdout { - println!("{columns}") - } else { - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open(&bench_conf.output_filename)?; - writeln!(file, "{columns}")?; - } - - Ok(SetupResult{bench_conf, columns: columns.to_string()}) -} diff --git a/benchmark_core/src/order.rs b/benchmark_core/src/order.rs index 7f31e95..a5ca687 100644 --- a/benchmark_core/src/order.rs +++ b/benchmark_core/src/order.rs @@ -6,7 +6,7 @@ use std::sync::{ Barrier, }; -use crate::traits::{ConcurrentQueue, Handle}; +use crate::traits::{ConcurrentQueue, HandleQueue}; #[allow(clippy::result_unit_err)] pub fn benchmark_order_box( diff --git a/benchmark_core/src/traits.rs b/benchmark_core/src/traits.rs index cccfc52..1599d64 100644 --- a/benchmark_core/src/traits.rs +++ b/benchmark_core/src/traits.rs @@ -1,7 +1,7 @@ -/// One of the traits that all queues implemented in the benchmark -/// needs to implement. +/// Trait that all queues need to implement pub trait ConcurrentQueue { - fn register(&self) -> impl Handle; + /// Returns a handle that exposes the queue API + fn register(&self) -> impl HandleQueue; /// Returns the name of the queue. fn get_id(&self) -> String; /// Used to create a new queue. @@ -9,12 +9,34 @@ pub trait ConcurrentQueue { fn new(size: usize) -> Self; } -/// One of the traits all queues implemented in the benchmark -/// needs to implement. -pub trait Handle { +/// Trait that exposes the correct API for queues +pub trait HandleQueue { /// Pushes an item to the queue. /// If it fails, returns the item pushed. fn push(&mut self, item: T) -> Result<(), T>; /// Pops an item from the queue. fn pop(&mut self) -> Option; } + +/// Trait that all priority queues need to implement +pub trait ConcurrentPriorityQueue { + /// Returns a handle that exposes the priority queue API + fn register(&self) -> impl HandlePriorityQueue; + /// Returns the name of the queue. + fn get_id(&self) -> String; + /// Used to create a new queue. + /// `size` is discarded for unbounded queues. + fn new(size: usize) -> Self; +} + +/// Trait that exposes the correct API for priority queues +pub trait HandlePriorityQueue { + /// Inserts an item into the priority queue. + /// In case of failure, returns the item and priority that failed to insert. + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)>; + /// Deletes the minimum item from the queue + /// Returns nothing if the queue is empty + fn delete_min(&mut self) -> Option; + /// Checks if the priority queue is empty + fn is_empty(&mut self) -> bool; +} diff --git a/queues/array_queue/Cargo.toml b/data_structures/fifo_queues/array_queue/Cargo.toml similarity index 87% rename from queues/array_queue/Cargo.toml rename to data_structures/fifo_queues/array_queue/Cargo.toml index e0ced3a..e89cf1b 100644 --- a/queues/array_queue/Cargo.toml +++ b/data_structures/fifo_queues/array_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/queues/array_queue/src/lib.rs b/data_structures/fifo_queues/array_queue/src/lib.rs similarity index 89% rename from queues/array_queue/src/lib.rs rename to data_structures/fifo_queues/array_queue/src/lib.rs index 76d712d..9b8ed8a 100644 --- a/queues/array_queue/src/lib.rs +++ b/data_structures/fifo_queues/array_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::queue::ArrayQueue; pub struct AQueueHandle<'a, T>{ @@ -11,7 +11,7 @@ pub struct AQueue{ impl ConcurrentQueue for AQueue { - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ AQueueHandle{ queue: self, } @@ -26,7 +26,7 @@ impl ConcurrentQueue for AQueue { } } -impl Handle for AQueueHandle<'_, T>{ +impl HandleQueue for AQueueHandle<'_, T>{ fn push(&mut self, value: T) -> Result<(), T>{ self.queue.array_queue.push(value) } @@ -59,6 +59,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: AQueue = AQueue { array_queue: ArrayQueue::new(10) diff --git a/data_structures/fifo_queues/array_queue/src/main.rs b/data_structures/fifo_queues/array_queue/src/main.rs new file mode 100644 index 0000000..450696e --- /dev/null +++ b/data_structures/fifo_queues/array_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("array_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/atomic_queue/Cargo.toml b/data_structures/fifo_queues/atomic_queue/Cargo.toml similarity index 88% rename from queues/atomic_queue/Cargo.toml rename to data_structures/fifo_queues/atomic_queue/Cargo.toml index 0f086cd..77275fe 100644 --- a/queues/atomic_queue/Cargo.toml +++ b/data_structures/fifo_queues/atomic_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } atomic_queue_upstream = { package = "atomic-queue", version = "2.2.0" } diff --git a/queues/atomic_queue/src/lib.rs b/data_structures/fifo_queues/atomic_queue/src/lib.rs similarity index 88% rename from queues/atomic_queue/src/lib.rs rename to data_structures/fifo_queues/atomic_queue/src/lib.rs index b3c8a0c..e4be0b2 100644 --- a/queues/atomic_queue/src/lib.rs +++ b/data_structures/fifo_queues/atomic_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct AtomicQueue { pub queue: atomic_queue_upstream::Queue, @@ -9,7 +9,7 @@ pub struct AtomicQueueHandle<'a, T> { } impl ConcurrentQueue for AtomicQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { AtomicQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for AtomicQueue { } } -impl Handle for AtomicQueueHandle<'_, T> { +impl HandleQueue for AtomicQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if !self.queue.queue.push(item) { return Err(T::default()); @@ -57,6 +57,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: AtomicQueue = AtomicQueue::new(10); diff --git a/data_structures/fifo_queues/atomic_queue/src/main.rs b/data_structures/fifo_queues/atomic_queue/src/main.rs new file mode 100644 index 0000000..188c1f1 --- /dev/null +++ b/data_structures/fifo_queues/atomic_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("atomic_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/basic_queue/Cargo.toml b/data_structures/fifo_queues/basic_queue/Cargo.toml similarity index 86% rename from queues/basic_queue/Cargo.toml rename to data_structures/fifo_queues/basic_queue/Cargo.toml index 625dbb2..85794d1 100644 --- a/queues/basic_queue/Cargo.toml +++ b/data_structures/fifo_queues/basic_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/basic_queue/src/lib.rs b/data_structures/fifo_queues/basic_queue/src/lib.rs similarity index 92% rename from queues/basic_queue/src/lib.rs rename to data_structures/fifo_queues/basic_queue/src/lib.rs index 8f48a74..f2decfe 100644 --- a/queues/basic_queue/src/lib.rs +++ b/data_structures/fifo_queues/basic_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{collections::VecDeque, sync::Mutex}; pub struct BQueue { @@ -39,7 +39,7 @@ pub struct BasicQueueHandle<'a, T> { } impl ConcurrentQueue for BasicQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BasicQueueHandle { queue: self, } @@ -54,7 +54,7 @@ impl ConcurrentQueue for BasicQueue { } } -impl Handle for BasicQueueHandle<'_, T> { +impl HandleQueue for BasicQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.bqueue.push(item); Ok(()) @@ -90,6 +90,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BasicQueue = BasicQueue { diff --git a/data_structures/fifo_queues/basic_queue/src/main.rs b/data_structures/fifo_queues/basic_queue/src/main.rs new file mode 100644 index 0000000..3d8e181 --- /dev/null +++ b/data_structures/fifo_queues/basic_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("basic_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/bbq/Cargo.toml b/data_structures/fifo_queues/bbq/Cargo.toml similarity index 88% rename from queues/bbq/Cargo.toml rename to data_structures/fifo_queues/bbq/Cargo.toml index 2c6a9f5..f6042e9 100644 --- a/queues/bbq/Cargo.toml +++ b/data_structures/fifo_queues/bbq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } bbq_upstream = { package = "bbq-rs", git = "https://github.com/WilleBerg/bbq", branch = "main" } diff --git a/queues/bbq/src/lib.rs b/data_structures/fifo_queues/bbq/src/lib.rs similarity index 87% rename from queues/bbq/src/lib.rs rename to data_structures/fifo_queues/bbq/src/lib.rs index d497c14..04fcd5c 100644 --- a/queues/bbq/src/lib.rs +++ b/data_structures/fifo_queues/bbq/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use bbq_upstream::BlockingQueue; pub struct BBQueue{ @@ -10,7 +10,7 @@ pub struct BBQHandle<'a, T> { } impl ConcurrentQueue for BBQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BBQHandle:: { queue: self, } @@ -25,7 +25,7 @@ impl ConcurrentQueue for BBQueue { } } -impl Handle for BBQHandle<'_, T> { +impl HandleQueue for BBQHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { self.queue.queue.push(item).expect("failed push"); Ok(()) @@ -47,6 +47,7 @@ mod tests { assert_eq!(q.queue.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BBQueue = BBQueue::new(100000); diff --git a/queues/basic_queue/src/main.rs b/data_structures/fifo_queues/bbq/src/main.rs similarity index 77% rename from queues/basic_queue/src/main.rs rename to data_structures/fifo_queues/bbq/src/main.rs index 64a1878..ff48662 100644 --- a/queues/basic_queue/src/main.rs +++ b/data_structures/fifo_queues/bbq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("basic_queue") { + match benchmark_fifo_queue::>("BBQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/queues/boost_queue_cpp/Cargo.toml b/data_structures/fifo_queues/boost_queue_cpp/Cargo.toml similarity index 88% rename from queues/boost_queue_cpp/Cargo.toml rename to data_structures/fifo_queues/boost_queue_cpp/Cargo.toml index b577c25..a7ce2de 100644 --- a/queues/boost_queue_cpp/Cargo.toml +++ b/data_structures/fifo_queues/boost_queue_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/boost_queue_cpp/build.rs b/data_structures/fifo_queues/boost_queue_cpp/build.rs similarity index 100% rename from queues/boost_queue_cpp/build.rs rename to data_structures/fifo_queues/boost_queue_cpp/build.rs diff --git a/queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp b/data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp similarity index 100% rename from queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp rename to data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.cpp diff --git a/queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp b/data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp similarity index 100% rename from queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp rename to data_structures/fifo_queues/boost_queue_cpp/cpp_src/boost_wrapper.hpp diff --git a/queues/boost_queue_cpp/src/lib.rs b/data_structures/fifo_queues/boost_queue_cpp/src/lib.rs similarity index 95% rename from queues/boost_queue_cpp/src/lib.rs rename to data_structures/fifo_queues/boost_queue_cpp/src/lib.rs index 72e08ff..504b241 100644 --- a/queues/boost_queue_cpp/src/lib.rs +++ b/data_structures/fifo_queues/boost_queue_cpp/src/lib.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -47,7 +47,7 @@ struct BoostCppQueueHandle<'a,T> { pub q: &'a BoostCppQueue } -impl Handle for BoostCppQueueHandle<'_,T> { +impl HandleQueue for BoostCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -68,7 +68,7 @@ impl Handle for BoostCppQueueHandle<'_,T> { } impl ConcurrentQueue for BoostCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BoostCppQueueHandle { q: self, } @@ -122,6 +122,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BoostCppQueue = BoostCppQueue::new(10); diff --git a/data_structures/fifo_queues/boost_queue_cpp/src/main.rs b/data_structures/fifo_queues/boost_queue_cpp/src/main.rs new file mode 100644 index 0000000..1b6b9af --- /dev/null +++ b/data_structures/fifo_queues/boost_queue_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("boost_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/bounded_concurrent_queue/Cargo.toml b/data_structures/fifo_queues/bounded_concurrent_queue/Cargo.toml similarity index 88% rename from queues/bounded_concurrent_queue/Cargo.toml rename to data_structures/fifo_queues/bounded_concurrent_queue/Cargo.toml index 8697eda..a87a01f 100644 --- a/queues/bounded_concurrent_queue/Cargo.toml +++ b/data_structures/fifo_queues/bounded_concurrent_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } concurrent-queue = { version = "2.5.0" } diff --git a/queues/bounded_concurrent_queue/src/lib.rs b/data_structures/fifo_queues/bounded_concurrent_queue/src/lib.rs similarity index 92% rename from queues/bounded_concurrent_queue/src/lib.rs rename to data_structures/fifo_queues/bounded_concurrent_queue/src/lib.rs index 43d8f94..49b3e4b 100644 --- a/queues/bounded_concurrent_queue/src/lib.rs +++ b/data_structures/fifo_queues/bounded_concurrent_queue/src/lib.rs @@ -1,7 +1,7 @@ use concurrent_queue::PushError; use log::warn; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct BoundedCQueueHandle<'a, T> { queue: &'a BoundedCQueue @@ -12,7 +12,7 @@ pub struct BoundedCQueue { } impl ConcurrentQueue for BoundedCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { BoundedCQueueHandle { queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for BoundedCQueue { } } -impl Handle for BoundedCQueueHandle<'_, T> { +impl HandleQueue for BoundedCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if let Err(err) = self.queue.cq.push(item) { let i = match err { @@ -81,6 +81,7 @@ mod tests { q.cq.push(1).unwrap(); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: BoundedCQueue = BoundedCQueue { diff --git a/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs b/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs new file mode 100644 index 0000000..e714c95 --- /dev/null +++ b/data_structures/fifo_queues/bounded_concurrent_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("bounded_concurrent_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/bounded_ringbuffer/Cargo.toml b/data_structures/fifo_queues/bounded_ringbuffer/Cargo.toml similarity index 86% rename from queues/bounded_ringbuffer/Cargo.toml rename to data_structures/fifo_queues/bounded_ringbuffer/Cargo.toml index a7b179f..1cefc07 100644 --- a/queues/bounded_ringbuffer/Cargo.toml +++ b/data_structures/fifo_queues/bounded_ringbuffer/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/bounded_ringbuffer/src/lib.rs b/data_structures/fifo_queues/bounded_ringbuffer/src/lib.rs similarity index 96% rename from queues/bounded_ringbuffer/src/lib.rs rename to data_structures/fifo_queues/bounded_ringbuffer/src/lib.rs index 7701239..364571f 100644 --- a/queues/bounded_ringbuffer/src/lib.rs +++ b/data_structures/fifo_queues/bounded_ringbuffer/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::sync::Mutex; pub struct BRingBuffer { @@ -67,7 +67,7 @@ pub struct BRingBufferHandle<'a, T>{ } -impl Handle for BRingBufferHandle<'_, T>{ +impl HandleQueue for BRingBufferHandle<'_, T>{ fn pop(&mut self) -> Option{ let mut buf = self.queue.brbuffer.bounded_ringbuffer.lock().unwrap(); buf.pop() @@ -80,7 +80,7 @@ impl Handle for BRingBufferHandle<'_, T>{ } impl ConcurrentQueue for BoundedRingBuffer{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ BRingBufferHandle:: { queue: self, } diff --git a/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs b/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs new file mode 100644 index 0000000..1562ebd --- /dev/null +++ b/data_structures/fifo_queues/bounded_ringbuffer/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("bounded_ringbuffer") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/faaa_queue/Cargo.toml b/data_structures/fifo_queues/faaa_queue/Cargo.toml similarity index 88% rename from queues/faaa_queue/Cargo.toml rename to data_structures/fifo_queues/faaa_queue/Cargo.toml index dfab814..dc5fd45 100644 --- a/queues/faaa_queue/Cargo.toml +++ b/data_structures/fifo_queues/faaa_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/queues/faaa_queue/src/lib.rs b/data_structures/fifo_queues/faaa_queue/src/lib.rs similarity index 97% rename from queues/faaa_queue/src/lib.rs rename to data_structures/fifo_queues/faaa_queue/src/lib.rs index 26c91e7..d113b89 100644 --- a/queues/faaa_queue/src/lib.rs +++ b/data_structures/fifo_queues/faaa_queue/src/lib.rs @@ -3,7 +3,7 @@ use std::{ptr::null_mut, sync::atomic::{AtomicPtr as RawAtomicPtr, AtomicUsize, use haphazard::{AtomicPtr as HpAtomicPtr, HazardPointer}; use crossbeam::utils::CachePadded; use log::trace; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; const BUFFER_SIZE: usize = 1024; @@ -136,7 +136,7 @@ pub struct FAAAQueueHandle<'a, T> { } impl ConcurrentQueue for FAAAQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { FAAAQueueHandle { queue: self, hp: HazardPointer::new(), @@ -154,7 +154,7 @@ impl ConcurrentQueue for FAAAQueue { } } -impl Handle for FAAAQueueHandle<'_, T> { +impl HandleQueue for FAAAQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { self.queue.enqueue(item, &mut self.hp); Ok(()) @@ -195,6 +195,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: FAAAQueue = FAAAQueue::new(10); diff --git a/data_structures/fifo_queues/faaa_queue/src/main.rs b/data_structures/fifo_queues/faaa_queue/src/main.rs new file mode 100644 index 0000000..f9529f0 --- /dev/null +++ b/data_structures/fifo_queues/faaa_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("faa_array_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/faaa_queue_cpp/Cargo.toml b/data_structures/fifo_queues/faaa_queue_cpp/Cargo.toml similarity index 88% rename from queues/faaa_queue_cpp/Cargo.toml rename to data_structures/fifo_queues/faaa_queue_cpp/Cargo.toml index e96e631..eeb17af 100644 --- a/queues/faaa_queue_cpp/Cargo.toml +++ b/data_structures/fifo_queues/faaa_queue_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/faaa_queue_cpp/build.rs b/data_structures/fifo_queues/faaa_queue_cpp/build.rs similarity index 100% rename from queues/faaa_queue_cpp/build.rs rename to data_structures/fifo_queues/faaa_queue_cpp/build.rs diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/FAAArrayQueue.hpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue/HazardPointers.hpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.cpp diff --git a/queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp b/data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp similarity index 100% rename from queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp rename to data_structures/fifo_queues/faaa_queue_cpp/cpp_src/faaa_queue_wrapper.hpp diff --git a/queues/faaa_queue_cpp/src/lib.rs b/data_structures/fifo_queues/faaa_queue_cpp/src/lib.rs similarity index 97% rename from queues/faaa_queue_cpp/src/lib.rs rename to data_structures/fifo_queues/faaa_queue_cpp/src/lib.rs index 6744732..548d8c2 100644 --- a/queues/faaa_queue_cpp/src/lib.rs +++ b/data_structures/fifo_queues/faaa_queue_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -80,7 +80,7 @@ struct FAAAQHandle<'a, T> { pub q: &'a FAAAQueue } -impl Handle for FAAAQHandle<'_, T> { +impl HandleQueue for FAAAQHandle<'_, T> { fn push(&mut self, item: T) -> Result <(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -100,7 +100,7 @@ impl Handle for FAAAQHandle<'_, T> { } impl ConcurrentQueue for FAAAQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { FAAAQHandle { q: self, } @@ -159,6 +159,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: FAAAQueue = FAAAQueue::new(); diff --git a/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs b/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs new file mode 100644 index 0000000..a8be8b0 --- /dev/null +++ b/data_structures/fifo_queues/faaa_queue_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("faaa_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/lcrq/Cargo.toml b/data_structures/fifo_queues/lcrq/Cargo.toml similarity index 88% rename from queues/lcrq/Cargo.toml rename to data_structures/fifo_queues/lcrq/Cargo.toml index 052bf4e..7160a82 100644 --- a/queues/lcrq/Cargo.toml +++ b/data_structures/fifo_queues/lcrq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/queues/lcrq/src/lib.rs b/data_structures/fifo_queues/lcrq/src/lib.rs similarity index 98% rename from queues/lcrq/src/lib.rs rename to data_structures/fifo_queues/lcrq/src/lib.rs index 4ed3577..8750284 100644 --- a/queues/lcrq/src/lib.rs +++ b/data_structures/fifo_queues/lcrq/src/lib.rs @@ -8,7 +8,7 @@ use haphazard::{raw::Pointer, AtomicPtr as HpAtomicPtr, HazardPointer}; #[allow(unused_imports)] use log::{debug, error, trace}; #[allow(unused_imports)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::utils::CachePadded; static RING_SIZE: usize = 1024; @@ -380,7 +380,7 @@ impl ConcurrentQueue for LCRQueue { fn new(_size: usize) -> Self { LCRQueue::new() } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LCRQueueHandle { queue: self, hp1: HazardPointer::new(), @@ -395,7 +395,7 @@ struct LCRQueueHandle<'a, T: std::fmt::Debug> { // hp2: HazardPointer<'static>, } -impl Handle for LCRQueueHandle<'_, T> { +impl HandleQueue for LCRQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.queue.dequeue(&mut self.hp1) } @@ -509,6 +509,7 @@ mod tests { assert_eq!(thesum, sum.into_inner()); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LCRQueue = LCRQueue::new(); diff --git a/queues/bbq/src/main.rs b/data_structures/fifo_queues/lcrq/src/main.rs similarity index 75% rename from queues/bbq/src/main.rs rename to data_structures/fifo_queues/lcrq/src/main.rs index eb7ee1c..8bac1df 100644 --- a/queues/bbq/src/main.rs +++ b/data_structures/fifo_queues/lcrq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("BBQ") { + match benchmark_fifo_queue::>("array_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/queues/lcrq_cpp/Cargo.toml b/data_structures/fifo_queues/lcrq_cpp/Cargo.toml similarity index 88% rename from queues/lcrq_cpp/Cargo.toml rename to data_structures/fifo_queues/lcrq_cpp/Cargo.toml index 46dd354..0c458b2 100644 --- a/queues/lcrq_cpp/Cargo.toml +++ b/data_structures/fifo_queues/lcrq_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/lcrq_cpp/build.rs b/data_structures/fifo_queues/lcrq_cpp/build.rs similarity index 100% rename from queues/lcrq_cpp/build.rs rename to data_structures/fifo_queues/lcrq_cpp/build.rs diff --git a/queues/lcrq_cpp/cpp_src/HazardPointers.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/HazardPointers.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/HazardPointers.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/HazardPointers.hpp diff --git a/queues/lcrq_cpp/cpp_src/LCRQueue.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/LCRQueue.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/LCRQueue.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/LCRQueue.hpp diff --git a/queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.cpp diff --git a/queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp b/data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp similarity index 100% rename from queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp rename to data_structures/fifo_queues/lcrq_cpp/cpp_src/lcrq_wrapper.hpp diff --git a/queues/lcrq_cpp/src/lib.rs b/data_structures/fifo_queues/lcrq_cpp/src/lib.rs similarity index 96% rename from queues/lcrq_cpp/src/lib.rs rename to data_structures/fifo_queues/lcrq_cpp/src/lib.rs index 92f064b..4e96850 100644 --- a/queues/lcrq_cpp/src/lib.rs +++ b/data_structures/fifo_queues/lcrq_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -75,7 +75,7 @@ struct LCRQHandle<'a, T> { pub q: &'a LCRQueue } -impl Handle for LCRQHandle<'_, T> { +impl HandleQueue for LCRQHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -95,7 +95,7 @@ impl Handle for LCRQHandle<'_, T> { } impl ConcurrentQueue for LCRQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LCRQHandle { q: self, } @@ -152,6 +152,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LCRQueue = LCRQueue::new(); diff --git a/data_structures/fifo_queues/lcrq_cpp/src/main.rs b/data_structures/fifo_queues/lcrq_cpp/src/main.rs new file mode 100644 index 0000000..3f792ea --- /dev/null +++ b/data_structures/fifo_queues/lcrq_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lcrq_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/lf_queue/Cargo.toml b/data_structures/fifo_queues/lf_queue/Cargo.toml similarity index 88% rename from queues/lf_queue/Cargo.toml rename to data_structures/fifo_queues/lf_queue/Cargo.toml index 6d39105..e161234 100644 --- a/queues/lf_queue/Cargo.toml +++ b/data_structures/fifo_queues/lf_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lf-queue-upstream = { package = "lf-queue", version = "0.1.0" } diff --git a/queues/lf_queue/src/lib.rs b/data_structures/fifo_queues/lf_queue/src/lib.rs similarity index 88% rename from queues/lf_queue/src/lib.rs rename to data_structures/fifo_queues/lf_queue/src/lib.rs index 6bae198..09d5e7e 100644 --- a/queues/lf_queue/src/lib.rs +++ b/data_structures/fifo_queues/lf_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LFQueue { pub lfq: lf_queue_upstream::Queue @@ -9,7 +9,7 @@ pub struct LFQueueHandle<'a, T> { } impl ConcurrentQueue for LFQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LFQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for LFQueue { } } -impl Handle for LFQueueHandle<'_, T> { +impl HandleQueue for LFQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.lfq.push(item); Ok(()) @@ -56,6 +56,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LFQueue = LFQueue::new(10); diff --git a/queues/atomic_queue/src/main.rs b/data_structures/fifo_queues/lf_queue/src/main.rs similarity index 75% rename from queues/atomic_queue/src/main.rs rename to data_structures/fifo_queues/lf_queue/src/main.rs index 881527b..e79475f 100644 --- a/queues/atomic_queue/src/main.rs +++ b/data_structures/fifo_queues/lf_queue/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("atomic_queue") { + match benchmark_fifo_queue::>("lf_queue") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/queues/lockfree_queue/Cargo.toml b/data_structures/fifo_queues/lockfree_queue/Cargo.toml similarity index 87% rename from queues/lockfree_queue/Cargo.toml rename to data_structures/fifo_queues/lockfree_queue/Cargo.toml index 5248041..43f118e 100644 --- a/queues/lockfree_queue/Cargo.toml +++ b/data_structures/fifo_queues/lockfree_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lockfree = { version = "0.5.1" } diff --git a/queues/lockfree_queue/src/lib.rs b/data_structures/fifo_queues/lockfree_queue/src/lib.rs similarity index 89% rename from queues/lockfree_queue/src/lib.rs rename to data_structures/fifo_queues/lockfree_queue/src/lib.rs index 9cd8fce..d0c0385 100644 --- a/queues/lockfree_queue/src/lib.rs +++ b/data_structures/fifo_queues/lockfree_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LockfreeQueueHandle<'a, T> { @@ -10,7 +10,7 @@ pub struct LockfreeQueue { } impl ConcurrentQueue for LockfreeQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LockfreeQueueHandle { queue: self, } @@ -25,7 +25,7 @@ impl ConcurrentQueue for LockfreeQueue { } } -impl Handle for LockfreeQueueHandle<'_, T> { +impl HandleQueue for LockfreeQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.lfq.push(item); Ok(()) @@ -60,6 +60,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LockfreeQueue = LockfreeQueue { diff --git a/data_structures/fifo_queues/lockfree_queue/src/main.rs b/data_structures/fifo_queues/lockfree_queue/src/main.rs new file mode 100644 index 0000000..8b28a75 --- /dev/null +++ b/data_structures/fifo_queues/lockfree_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lockfree_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/lprq/Cargo.toml b/data_structures/fifo_queues/lprq/Cargo.toml similarity index 88% rename from queues/lprq/Cargo.toml rename to data_structures/fifo_queues/lprq/Cargo.toml index b02f81c..47d27fa 100644 --- a/queues/lprq/Cargo.toml +++ b/data_structures/fifo_queues/lprq/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/queues/lprq/src/lib.rs b/data_structures/fifo_queues/lprq/src/lib.rs similarity index 98% rename from queues/lprq/src/lib.rs rename to data_structures/fifo_queues/lprq/src/lib.rs index 048e208..5edfce7 100644 --- a/queues/lprq/src/lib.rs +++ b/data_structures/fifo_queues/lprq/src/lib.rs @@ -3,7 +3,7 @@ use std::sync::atomic::Ordering::SeqCst as SeqCst; use haphazard::{AtomicPtr as HpAtomicPtr, HazardPointer}; use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::utils::CachePadded; static RING_SIZE: u64 = 1024; @@ -338,7 +338,7 @@ impl ConcurrentQueue for LPRQueue { fn new(_size: usize) -> Self { LPRQueue::new() } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LPRQueueHandle { queue: self, hp: HazardPointer::new(), @@ -351,7 +351,7 @@ struct LPRQueueHandle<'a, T> { hp: HazardPointer<'static>, } -impl Handle for LPRQueueHandle<'_, T> { +impl HandleQueue for LPRQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.queue.dequeue(&mut self.hp) } @@ -440,6 +440,7 @@ mod tests { assert_eq!(thesum, sum.into_inner()); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LPRQueue = LPRQueue::new(); diff --git a/queues/lprq/src/lprq_rs.rs b/data_structures/fifo_queues/lprq/src/lprq_rs.rs similarity index 87% rename from queues/lprq/src/lprq_rs.rs rename to data_structures/fifo_queues/lprq/src/lprq_rs.rs index dca1056..4894195 100644 --- a/queues/lprq/src/lprq_rs.rs +++ b/data_structures/fifo_queues/lprq/src/lprq_rs.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use lprq_rs::LPRQueue; pub struct LPRQueueRSHandle<'a, T>{ @@ -10,7 +10,7 @@ pub struct LPRQRS{ } impl ConcurrentQueue for LPRQRS{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ LPRQueueRSHandle{ queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for LPRQRS{ } } -impl Handle for LPRQueueRSHandle<'_, T> { +impl HandleQueue for LPRQueueRSHandle<'_, T> { fn push(&mut self, value: T) -> Result<(), T> { self.queue.lprqueue.enqueue(value); Ok(()) @@ -56,6 +56,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: LPRQRS = LPRQRS::new(100); if benchmark_core::order::benchmark_order_i32(q, 10, 5, true, 10).is_err() { diff --git a/queues/array_queue/src/main.rs b/data_structures/fifo_queues/lprq/src/main.rs similarity index 76% rename from queues/array_queue/src/main.rs rename to data_structures/fifo_queues/lprq/src/main.rs index 43a4e90..11d1470 100644 --- a/queues/array_queue/src/main.rs +++ b/data_structures/fifo_queues/lprq/src/main.rs @@ -1,4 +1,5 @@ use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; fn main() { @@ -10,7 +11,7 @@ fn main() { } log::info!("Starting benchmark"); - match benchmark_core::benchmark_target_queue::>("array_queue") { + match benchmark_fifo_queue::>("LPRQ") { Ok(_) => println!("Benchmark done."), Err(e) => { eprintln!("Benchmark received error: {}", e); diff --git a/queues/lprq_cpp/Cargo.toml b/data_structures/fifo_queues/lprq_cpp/Cargo.toml similarity index 88% rename from queues/lprq_cpp/Cargo.toml rename to data_structures/fifo_queues/lprq_cpp/Cargo.toml index 71a56fd..cd556b7 100644 --- a/queues/lprq_cpp/Cargo.toml +++ b/data_structures/fifo_queues/lprq_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/lprq_cpp/build.rs b/data_structures/fifo_queues/lprq_cpp/build.rs similarity index 100% rename from queues/lprq_cpp/build.rs rename to data_structures/fifo_queues/lprq_cpp/build.rs diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.dockerignore diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/.gitignore diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CLI11.cmake diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/CMakeLists.txt diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Dockerfile diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/Gtest.cmake diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/LICENSE diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/README.md diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/CacheRemap.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Forked.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/HazardPointers.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LPRQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/LinkedRingQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/MetaprogrammingUtils.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Metrics.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ModLCRQueue.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/RQCell.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/Stats.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/ThreadGroup.hpp diff --git a/queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/cpp-ring-queues-research/include/x86AtomicOps.hpp diff --git a/queues/lprq_cpp/cpp_src/lprq_wrapper.cpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.cpp similarity index 100% rename from queues/lprq_cpp/cpp_src/lprq_wrapper.cpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.cpp diff --git a/queues/lprq_cpp/cpp_src/lprq_wrapper.hpp b/data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.hpp similarity index 100% rename from queues/lprq_cpp/cpp_src/lprq_wrapper.hpp rename to data_structures/fifo_queues/lprq_cpp/cpp_src/lprq_wrapper.hpp diff --git a/queues/lprq_cpp/src/lib.rs b/data_structures/fifo_queues/lprq_cpp/src/lib.rs similarity index 96% rename from queues/lprq_cpp/src/lib.rs rename to data_structures/fifo_queues/lprq_cpp/src/lib.rs index 6ab3a4b..61306ec 100644 --- a/queues/lprq_cpp/src/lib.rs +++ b/data_structures/fifo_queues/lprq_cpp/src/lib.rs @@ -4,7 +4,7 @@ use std::{cell::Cell, sync::atomic::{AtomicI32, Ordering}}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -80,7 +80,7 @@ struct LPRQHandle<'a, T> { pub q: &'a LPRQueue } -impl Handle for LPRQHandle<'_, T> { +impl HandleQueue for LPRQHandle<'_, T> { fn push(&mut self, item: T) -> Result <(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -100,7 +100,7 @@ impl Handle for LPRQHandle<'_, T> { } impl ConcurrentQueue for LPRQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LPRQHandle { q: self, } @@ -157,6 +157,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 4); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: LPRQueue = LPRQueue::new(); diff --git a/data_structures/fifo_queues/lprq_cpp/src/main.rs b/data_structures/fifo_queues/lprq_cpp/src/main.rs new file mode 100644 index 0000000..b6219e3 --- /dev/null +++ b/data_structures/fifo_queues/lprq_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lprq_queue_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/moodycamel_cpp/Cargo.toml b/data_structures/fifo_queues/moodycamel_cpp/Cargo.toml similarity index 88% rename from queues/moodycamel_cpp/Cargo.toml rename to data_structures/fifo_queues/moodycamel_cpp/Cargo.toml index edbd362..4a09f8c 100644 --- a/queues/moodycamel_cpp/Cargo.toml +++ b/data_structures/fifo_queues/moodycamel_cpp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/moodycamel_cpp/build.rs b/data_structures/fifo_queues/moodycamel_cpp/build.rs similarity index 100% rename from queues/moodycamel_cpp/build.rs rename to data_structures/fifo_queues/moodycamel_cpp/build.rs diff --git a/queues/moodycamel_cpp/cpp_src/concurrentqueue b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue similarity index 100% rename from queues/moodycamel_cpp/cpp_src/concurrentqueue rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/concurrentqueue diff --git a/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp similarity index 100% rename from queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.cpp diff --git a/queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp b/data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp similarity index 100% rename from queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp rename to data_structures/fifo_queues/moodycamel_cpp/cpp_src/moodycamel_wrapper.hpp diff --git a/queues/moodycamel_cpp/src/lib.rs b/data_structures/fifo_queues/moodycamel_cpp/src/lib.rs similarity index 96% rename from queues/moodycamel_cpp/src/lib.rs rename to data_structures/fifo_queues/moodycamel_cpp/src/lib.rs index a110d59..eb54222 100644 --- a/queues/moodycamel_cpp/src/lib.rs +++ b/data_structures/fifo_queues/moodycamel_cpp/src/lib.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -49,7 +49,7 @@ struct MoodyCamelCppQueueHandle<'a,T> { pub q: &'a MoodyCamelCppQueue } -impl Handle for MoodyCamelCppQueueHandle<'_,T> { +impl HandleQueue for MoodyCamelCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T>{ let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -72,7 +72,7 @@ impl Handle for MoodyCamelCppQueueHandle<'_,T> { } impl ConcurrentQueue for MoodyCamelCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { MoodyCamelCppQueueHandle { q: self, } diff --git a/data_structures/fifo_queues/moodycamel_cpp/src/main.rs b/data_structures/fifo_queues/moodycamel_cpp/src/main.rs new file mode 100644 index 0000000..c5dc266 --- /dev/null +++ b/data_structures/fifo_queues/moodycamel_cpp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("moodycamel_cpp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/ms_queue/Cargo.toml b/data_structures/fifo_queues/ms_queue/Cargo.toml similarity index 87% rename from queues/ms_queue/Cargo.toml rename to data_structures/fifo_queues/ms_queue/Cargo.toml index d410ab4..553cfd4 100644 --- a/queues/ms_queue/Cargo.toml +++ b/data_structures/fifo_queues/ms_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/queues/ms_queue/src/lib.rs b/data_structures/fifo_queues/ms_queue/src/lib.rs similarity index 97% rename from queues/ms_queue/src/lib.rs rename to data_structures/fifo_queues/ms_queue/src/lib.rs index a80e062..8b05ae9 100644 --- a/queues/ms_queue/src/lib.rs +++ b/data_structures/fifo_queues/ms_queue/src/lib.rs @@ -3,7 +3,7 @@ use std::mem::MaybeUninit; use haphazard::{raw::Pointer, AtomicPtr, HazardPointer}; use log::{error, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; struct Node { next: AtomicPtr>, @@ -162,7 +162,7 @@ pub struct MSQueueHandle<'a, T> { } impl ConcurrentQueue for MSQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { MSQueueHandle { queue: self, hp1: HazardPointer::new(), @@ -181,7 +181,7 @@ impl ConcurrentQueue for MSQueue { } } -impl Handle for MSQueueHandle<'_, T> { +impl HandleQueue for MSQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ self.queue.enqueue(&mut self.hp1, item); Ok(()) @@ -215,6 +215,7 @@ mod tests { } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: MSQueue = MSQueue::new(10); diff --git a/data_structures/fifo_queues/ms_queue/src/main.rs b/data_structures/fifo_queues/ms_queue/src/main.rs new file mode 100644 index 0000000..f0035f4 --- /dev/null +++ b/data_structures/fifo_queues/ms_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("ms_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/scc2_queue/Cargo.toml b/data_structures/fifo_queues/scc2_queue/Cargo.toml similarity index 87% rename from queues/scc2_queue/Cargo.toml rename to data_structures/fifo_queues/scc2_queue/Cargo.toml index ea1f73c..e77db06 100644 --- a/queues/scc2_queue/Cargo.toml +++ b/data_structures/fifo_queues/scc2_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc2 = { version = "2.4.1" } diff --git a/queues/scc2_queue/src/lib.rs b/data_structures/fifo_queues/scc2_queue/src/lib.rs similarity index 88% rename from queues/scc2_queue/src/lib.rs rename to data_structures/fifo_queues/scc2_queue/src/lib.rs index 3950532..93306b9 100644 --- a/queues/scc2_queue/src/lib.rs +++ b/data_structures/fifo_queues/scc2_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCC2Queue { pub queue: scc2::Queue, @@ -9,7 +9,7 @@ pub struct SCC2QueueHandle<'a, T: 'static> { } impl ConcurrentQueue for SCC2Queue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCC2QueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCC2Queue { } } -impl Handle for SCC2QueueHandle<'_, T> { +impl HandleQueue for SCC2QueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/fifo_queues/scc2_queue/src/main.rs b/data_structures/fifo_queues/scc2_queue/src/main.rs new file mode 100644 index 0000000..78d0ad9 --- /dev/null +++ b/data_structures/fifo_queues/scc2_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc2_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/scc_queue/Cargo.toml b/data_structures/fifo_queues/scc_queue/Cargo.toml similarity index 87% rename from queues/scc_queue/Cargo.toml rename to data_structures/fifo_queues/scc_queue/Cargo.toml index cbfd923..731f792 100644 --- a/queues/scc_queue/Cargo.toml +++ b/data_structures/fifo_queues/scc_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc = { version = "2.3.3" } diff --git a/queues/scc_queue/src/lib.rs b/data_structures/fifo_queues/scc_queue/src/lib.rs similarity index 88% rename from queues/scc_queue/src/lib.rs rename to data_structures/fifo_queues/scc_queue/src/lib.rs index b4987e1..2db110f 100644 --- a/queues/scc_queue/src/lib.rs +++ b/data_structures/fifo_queues/scc_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCCQueue { pub queue: scc::Queue, @@ -9,7 +9,7 @@ pub struct SCCQueueHandle<'a, T: 'static> { } impl ConcurrentQueue for SCCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCCQueueHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCCQueue { } } -impl Handle for SCCQueueHandle<'_, T> { +impl HandleQueue for SCCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/fifo_queues/scc_queue/src/main.rs b/data_structures/fifo_queues/scc_queue/src/main.rs new file mode 100644 index 0000000..c3b5997 --- /dev/null +++ b/data_structures/fifo_queues/scc_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/seg_queue/Cargo.toml b/data_structures/fifo_queues/seg_queue/Cargo.toml similarity index 87% rename from queues/seg_queue/Cargo.toml rename to data_structures/fifo_queues/seg_queue/Cargo.toml index ea291bf..b3bb992 100644 --- a/queues/seg_queue/Cargo.toml +++ b/data_structures/fifo_queues/seg_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } crossbeam = { workspace = true } diff --git a/queues/seg_queue/src/lib.rs b/data_structures/fifo_queues/seg_queue/src/lib.rs similarity index 87% rename from queues/seg_queue/src/lib.rs rename to data_structures/fifo_queues/seg_queue/src/lib.rs index 2b6ac84..3089bbb 100644 --- a/queues/seg_queue/src/lib.rs +++ b/data_structures/fifo_queues/seg_queue/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use crossbeam::queue::SegQueue; pub struct SegQueueHandle<'a, T>{ @@ -10,7 +10,7 @@ pub struct SQueue{ } impl ConcurrentQueue for SQueue{ - fn register(&self) -> impl Handle{ + fn register(&self) -> impl HandleQueue{ SegQueueHandle{ queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for SQueue{ } } -impl Handle for SegQueueHandle<'_, T> { +impl HandleQueue for SegQueueHandle<'_, T> { fn push(&mut self, value: T) -> Result<(), T> { self.queue.seg_queue.push(value); Ok(()) @@ -56,6 +56,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let q: SQueue = SQueue::new(100); if benchmark_core::order::benchmark_order_i32(q, 10, 5, true, 10).is_err() { diff --git a/data_structures/fifo_queues/seg_queue/src/main.rs b/data_structures/fifo_queues/seg_queue/src/main.rs new file mode 100644 index 0000000..8007589 --- /dev/null +++ b/data_structures/fifo_queues/seg_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("seg_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/tz_queue_hp/Cargo.toml b/data_structures/fifo_queues/tz_queue_hp/Cargo.toml similarity index 87% rename from queues/tz_queue_hp/Cargo.toml rename to data_structures/fifo_queues/tz_queue_hp/Cargo.toml index 921b7ab..9cac851 100644 --- a/queues/tz_queue_hp/Cargo.toml +++ b/data_structures/fifo_queues/tz_queue_hp/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } haphazard = { workspace = true } diff --git a/queues/tz_queue_hp/src/lib.rs b/data_structures/fifo_queues/tz_queue_hp/src/lib.rs similarity index 98% rename from queues/tz_queue_hp/src/lib.rs rename to data_structures/fifo_queues/tz_queue_hp/src/lib.rs index 55674e4..e04ee58 100644 --- a/queues/tz_queue_hp/src/lib.rs +++ b/data_structures/fifo_queues/tz_queue_hp/src/lib.rs @@ -1,7 +1,7 @@ #[allow(unused_imports)] use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{fmt::{Debug, Display}, sync::atomic::{AtomicUsize, Ordering}}; use haphazard::HazardPointer; @@ -198,7 +198,7 @@ impl ConcurrentQueue for TZQueue { fn get_id(&self) -> String { String::from("tz_queue_hp") } - fn register(&self) -> impl benchmark_core::traits::Handle { + fn register(&self) -> impl benchmark_core::traits::HandleQueue { TZQueueHandle { q: self, hp1: HazardPointer::new(), @@ -211,7 +211,7 @@ struct TZQueueHandle<'a, T: Copy> { hp1: HazardPointer<'static>, } -impl Handle for TZQueueHandle<'_, T> { +impl HandleQueue for TZQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.q.dequeue(&mut self.hp1) } @@ -347,6 +347,7 @@ mod tests { drop(q); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: TZQueue = TZQueue::new(1000000); diff --git a/data_structures/fifo_queues/tz_queue_hp/src/main.rs b/data_structures/fifo_queues/tz_queue_hp/src/main.rs new file mode 100644 index 0000000..ee6804b --- /dev/null +++ b/data_structures/fifo_queues/tz_queue_hp/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("tz_queue_hp") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/tz_queue_leak/Cargo.toml b/data_structures/fifo_queues/tz_queue_leak/Cargo.toml similarity index 86% rename from queues/tz_queue_leak/Cargo.toml rename to data_structures/fifo_queues/tz_queue_leak/Cargo.toml index ca3181b..5abb362 100644 --- a/queues/tz_queue_leak/Cargo.toml +++ b/data_structures/fifo_queues/tz_queue_leak/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } diff --git a/queues/tz_queue_leak/src/lib.rs b/data_structures/fifo_queues/tz_queue_leak/src/lib.rs similarity index 98% rename from queues/tz_queue_leak/src/lib.rs rename to data_structures/fifo_queues/tz_queue_leak/src/lib.rs index 000f9fb..983e5dd 100644 --- a/queues/tz_queue_leak/src/lib.rs +++ b/data_structures/fifo_queues/tz_queue_leak/src/lib.rs @@ -1,7 +1,7 @@ #[allow(unused_imports)] use log::{debug, trace}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; use std::{fmt::{Debug, Display}, sync::atomic::{AtomicPtr, AtomicUsize, Ordering}}; #[derive(Copy, Clone, Debug)] @@ -189,7 +189,7 @@ impl ConcurrentQueue for TZQueue { fn get_id(&self) -> String { String::from("tz_queue") } - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { TZQueueHandle { q: self } @@ -200,7 +200,7 @@ struct TZQueueHandle<'a, T: Copy> { q: &'a TZQueue, } -impl Handle for TZQueueHandle<'_, T> { +impl HandleQueue for TZQueueHandle<'_, T> { fn pop(&mut self) -> Option { self.q.dequeue() } @@ -330,6 +330,7 @@ mod tests { drop(q); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: TZQueue = TZQueue::new(10); diff --git a/data_structures/fifo_queues/tz_queue_leak/src/main.rs b/data_structures/fifo_queues/tz_queue_leak/src/main.rs new file mode 100644 index 0000000..b586f34 --- /dev/null +++ b/data_structures/fifo_queues/tz_queue_leak/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("tz_queue_leak") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/unbounded_concurrent_queue/Cargo.toml b/data_structures/fifo_queues/unbounded_concurrent_queue/Cargo.toml similarity index 88% rename from queues/unbounded_concurrent_queue/Cargo.toml rename to data_structures/fifo_queues/unbounded_concurrent_queue/Cargo.toml index 9905d50..2927d1a 100644 --- a/queues/unbounded_concurrent_queue/Cargo.toml +++ b/data_structures/fifo_queues/unbounded_concurrent_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } concurrent-queue = { version = "2.5.0" } diff --git a/queues/unbounded_concurrent_queue/src/lib.rs b/data_structures/fifo_queues/unbounded_concurrent_queue/src/lib.rs similarity index 91% rename from queues/unbounded_concurrent_queue/src/lib.rs rename to data_structures/fifo_queues/unbounded_concurrent_queue/src/lib.rs index 472f5ea..1bbd055 100644 --- a/queues/unbounded_concurrent_queue/src/lib.rs +++ b/data_structures/fifo_queues/unbounded_concurrent_queue/src/lib.rs @@ -1,7 +1,7 @@ use concurrent_queue::PushError; use log::warn; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct UnboundedCQueue { q: concurrent_queue::ConcurrentQueue, @@ -12,7 +12,7 @@ pub struct UnboundedCQueueHandle<'a, T> { } impl ConcurrentQueue for UnboundedCQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { UnboundedCQueueHandle { queue: self, } @@ -27,7 +27,7 @@ impl ConcurrentQueue for UnboundedCQueue { } } -impl Handle for UnboundedCQueueHandle<'_, T> { +impl HandleQueue for UnboundedCQueueHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T>{ if let Err(err) = self.queue.q.push(item) { let i = match err { @@ -68,6 +68,7 @@ mod tests { assert_eq!(handle.pop().unwrap(), 1); } #[test] + #[ignore] fn test_order() { let _ = env_logger::builder().is_test(true).try_init(); let q: UnboundedCQueue = UnboundedCQueue::new(0); diff --git a/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs b/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs new file mode 100644 index 0000000..b1c1c8b --- /dev/null +++ b/data_structures/fifo_queues/unbounded_concurrent_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("unbounded_concurrent_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/wf_queue/Cargo.toml b/data_structures/fifo_queues/wf_queue/Cargo.toml similarity index 89% rename from queues/wf_queue/Cargo.toml rename to data_structures/fifo_queues/wf_queue/Cargo.toml index b06c6bd..f07bc5f 100644 --- a/queues/wf_queue/Cargo.toml +++ b/data_structures/fifo_queues/wf_queue/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } wfqueue_upstream = { package = "wfqueue", git = "https://github.com/WilleBerg/wfqueue", branch = "master" } diff --git a/queues/wf_queue/src/lib.rs b/data_structures/fifo_queues/wf_queue/src/lib.rs similarity index 87% rename from queues/wf_queue/src/lib.rs rename to data_structures/fifo_queues/wf_queue/src/lib.rs index 2c3ff6c..c66cc43 100644 --- a/queues/wf_queue/src/lib.rs +++ b/data_structures/fifo_queues/wf_queue/src/lib.rs @@ -1,5 +1,5 @@ use wfqueue_upstream::{Queueable, WfQueue}; -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct WFQueueHandle<'a, T> { queue: &'a WFQueue @@ -13,7 +13,7 @@ impl ConcurrentQueue for WFQueue where Box: Queueable { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { WFQueueHandle { queue: self, } @@ -30,7 +30,7 @@ where } } -impl Handle for WFQueueHandle<'_, T> +impl HandleQueue for WFQueueHandle<'_, T> where Box: Queueable { @@ -49,7 +49,7 @@ where #[cfg(test)] mod tests { - use super::{ConcurrentQueue, Handle, WFQueue}; + use super::{ConcurrentQueue, HandleQueue, WFQueue}; // #[test] // fn create_bq() { diff --git a/data_structures/fifo_queues/wf_queue/src/main.rs b/data_structures/fifo_queues/wf_queue/src/main.rs new file mode 100644 index 0000000..05a910c --- /dev/null +++ b/data_structures/fifo_queues/wf_queue/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("wf_queue") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/data_structures/priority_queues/basic_priority_queue/Cargo.toml b/data_structures/priority_queues/basic_priority_queue/Cargo.toml new file mode 100644 index 0000000..e7cc65b --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "basic_priority_queue" +version = "0.1.0" +edition = "2021" + +[dependencies] +benchmark_core = { path = "../../../benchmark_core" } +log = { workspace = true } +env_logger = { workspace = true, optional=true } + +[features] +default = ["log/release_max_level_info", "dep:env_logger"] +verbose-release = ["log/release_max_level_trace", "dep:env_logger"] +silent-release = ["log/release_max_level_off"] diff --git a/data_structures/priority_queues/basic_priority_queue/src/lib.rs b/data_structures/priority_queues/basic_priority_queue/src/lib.rs new file mode 100644 index 0000000..bae731f --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/src/lib.rs @@ -0,0 +1,153 @@ +use benchmark_core::traits::{ConcurrentPriorityQueue, HandlePriorityQueue}; +use std::cmp::{Ordering, Reverse}; +use std::{collections::binary_heap::BinaryHeap, sync::Mutex}; + +pub struct KeyValuePair { + key: Reverse

, + item: T, +} + +impl KeyValuePair { + pub fn new(key: P, item: T) -> Self { + Self { + key: Reverse(key), + item, + } + } +} + +impl Ord for KeyValuePair { + fn cmp(&self, other: &Self) -> Ordering { + self.key.cmp(&other.key) + } +} + +impl PartialOrd for KeyValuePair { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for KeyValuePair { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } +} + +impl Eq for KeyValuePair {} + +pub struct BinHeapWrap { + bin_heap: Mutex>>, +} + +impl BinHeapWrap { + pub fn delete_min(&self) -> Option> { + let mut q = self.bin_heap.lock().unwrap(); + q.pop() + } + + pub fn insert(&self, item: KeyValuePair) { + let mut q = self.bin_heap.lock().unwrap(); + q.push(item); + } + + pub fn is_empty(&self) -> bool { + self.bin_heap.lock().unwrap().is_empty() + } + + pub fn new() -> Self { + BinHeapWrap { + bin_heap: Mutex::new(BinaryHeap::new()), + } + } +} + +impl Default for BinHeapWrap { + fn default() -> Self { + Self::new() + } +} + +pub struct BasicPriorityQueue { + pub basic_priority_queue: BinHeapWrap, +} + +pub struct BasicPriorityQueueHandle<'a, P: Ord, T> { + priority_queue: &'a BasicPriorityQueue, +} + +impl ConcurrentPriorityQueue for BasicPriorityQueue { + fn register(&self) -> impl HandlePriorityQueue { + BasicPriorityQueueHandle { + priority_queue: self, + } + } + fn get_id(&self) -> String { + String::from("basic_priority_queue") + } + fn new(_size: usize) -> Self { + BasicPriorityQueue { + basic_priority_queue: BinHeapWrap::::new(), + } + } +} + +impl HandlePriorityQueue + for BasicPriorityQueueHandle<'_, P, T> +{ + fn insert(&mut self, priority: P, item: T) -> Result<(), (P, T)> { + let kv_pair = KeyValuePair::new(priority, item); + self.priority_queue.basic_priority_queue.insert(kv_pair); + Ok(()) + } + fn delete_min(&mut self) -> Option { + match self.priority_queue.basic_priority_queue.delete_min() { + Some(kv_pair) => Some(kv_pair.item), + None => None, + } + } + fn is_empty(&mut self) -> bool { + self.priority_queue.basic_priority_queue.is_empty() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_basic_priority_queue() { + let pq: BasicPriorityQueue = BasicPriorityQueue { + basic_priority_queue: BinHeapWrap::new(), + }; + pq.basic_priority_queue.insert(KeyValuePair::new(1, 10)); + assert_eq!(pq.basic_priority_queue.delete_min().unwrap().item, 10); + } + + #[test] + fn register_basic_priority_queue() { + let pq = BasicPriorityQueue::::new(0); + let mut handle = pq.register(); + handle.insert(1, 10).unwrap(); + assert_eq!(handle.delete_min().unwrap(), 10); + } + + #[test] + fn basic_usage_basic_priority_queue() { + let pq = BasicPriorityQueue::::new(0); + + let mut handle = pq.register(); + assert_eq!(handle.insert(5, 50), Ok(())); + assert_eq!(handle.insert(4, 40), Ok(())); + assert_eq!(handle.insert(1, 10), Ok(())); + assert_eq!(handle.insert(2, 20), Ok(())); + assert_eq!(handle.insert(3, 30), Ok(())); + + assert_eq!(handle.delete_min(), Some(10)); + assert_eq!(handle.delete_min(), Some(20)); + assert_eq!(handle.delete_min(), Some(30)); + assert_eq!(handle.delete_min(), Some(40)); + assert_eq!(handle.delete_min(), Some(50)); + assert_eq!(handle.delete_min(), None); + } +} diff --git a/data_structures/priority_queues/basic_priority_queue/src/main.rs b/data_structures/priority_queues/basic_priority_queue/src/main.rs new file mode 100644 index 0000000..93e4534 --- /dev/null +++ b/data_structures/priority_queues/basic_priority_queue/src/main.rs @@ -0,0 +1,24 @@ +use benchmark_core::benchmarks::priority_queue_benchmarks::benchmark_priority_queue; +use log::*; + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_priority_queue::< + basic_priority_queue::BasicPriorityQueue, + i32, + >("basic_priority_queue") + { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/stacks/lockfree_stack/Cargo.toml b/data_structures/stacks/lockfree_stack/Cargo.toml similarity index 87% rename from stacks/lockfree_stack/Cargo.toml rename to data_structures/stacks/lockfree_stack/Cargo.toml index 64dbee3..5462c07 100644 --- a/stacks/lockfree_stack/Cargo.toml +++ b/data_structures/stacks/lockfree_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } lockfree = { version = "0.5.1" } diff --git a/stacks/lockfree_stack/src/lib.rs b/data_structures/stacks/lockfree_stack/src/lib.rs similarity index 87% rename from stacks/lockfree_stack/src/lib.rs rename to data_structures/stacks/lockfree_stack/src/lib.rs index 5b01652..59fb756 100644 --- a/stacks/lockfree_stack/src/lib.rs +++ b/data_structures/stacks/lockfree_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct LockfreeStack{ pub lfs: lockfree::stack::Stack } @@ -8,7 +8,7 @@ pub struct LockFreeStacKHandle<'a, T> { } impl ConcurrentQueue for LockfreeStack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { LockFreeStacKHandle{ stack: self, } @@ -23,7 +23,7 @@ impl ConcurrentQueue for LockfreeStack { } } -impl Handle for LockFreeStacKHandle<'_, T>{ +impl HandleQueue for LockFreeStacKHandle<'_, T>{ fn push(&mut self, item: T) -> Result<(), T>{ self.stack.lfs.push(item); Ok(()) diff --git a/data_structures/stacks/lockfree_stack/src/main.rs b/data_structures/stacks/lockfree_stack/src/main.rs new file mode 100644 index 0000000..dc00667 --- /dev/null +++ b/data_structures/stacks/lockfree_stack/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("lockfree_stack") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/stacks/scc2_stack/Cargo.toml b/data_structures/stacks/scc2_stack/Cargo.toml similarity index 87% rename from stacks/scc2_stack/Cargo.toml rename to data_structures/stacks/scc2_stack/Cargo.toml index d25c19b..f9ab854 100644 --- a/stacks/scc2_stack/Cargo.toml +++ b/data_structures/stacks/scc2_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc2 = { version = "2.4.1" } diff --git a/stacks/scc2_stack/src/lib.rs b/data_structures/stacks/scc2_stack/src/lib.rs similarity index 86% rename from stacks/scc2_stack/src/lib.rs rename to data_structures/stacks/scc2_stack/src/lib.rs index d74c896..0521198 100644 --- a/stacks/scc2_stack/src/lib.rs +++ b/data_structures/stacks/scc2_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCC2Stack { pub queue: scc2::Stack, @@ -9,7 +9,7 @@ pub struct SCC2StackHandle<'a, T: 'static> { } impl ConcurrentQueue for SCC2Stack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCC2StackHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCC2Stack { } } -impl Handle for SCC2StackHandle<'_, T> { +impl HandleQueue for SCC2StackHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/stacks/scc2_stack/src/main.rs b/data_structures/stacks/scc2_stack/src/main.rs new file mode 100644 index 0000000..789858b --- /dev/null +++ b/data_structures/stacks/scc2_stack/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc2_stack") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/stacks/scc_stack/Cargo.toml b/data_structures/stacks/scc_stack/Cargo.toml similarity index 87% rename from stacks/scc_stack/Cargo.toml rename to data_structures/stacks/scc_stack/Cargo.toml index c19a2d0..5ac252f 100644 --- a/stacks/scc_stack/Cargo.toml +++ b/data_structures/stacks/scc_stack/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -benchmark_core = { path = "../../benchmark_core" } +benchmark_core = { path = "../../../benchmark_core" } log = { workspace = true } env_logger = { workspace = true, optional=true } scc = { version = "2.3.3" } diff --git a/stacks/scc_stack/src/lib.rs b/data_structures/stacks/scc_stack/src/lib.rs similarity index 86% rename from stacks/scc_stack/src/lib.rs rename to data_structures/stacks/scc_stack/src/lib.rs index 561bef8..518f4e8 100644 --- a/stacks/scc_stack/src/lib.rs +++ b/data_structures/stacks/scc_stack/src/lib.rs @@ -1,4 +1,4 @@ -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; pub struct SCCStack { pub queue: scc::Stack, @@ -9,7 +9,7 @@ pub struct SCCStackHandle<'a, T: 'static> { } impl ConcurrentQueue for SCCStack { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { SCCStackHandle { queue: self, } @@ -24,7 +24,7 @@ impl ConcurrentQueue for SCCStack { } } -impl Handle for SCCStackHandle<'_, T> { +impl HandleQueue for SCCStackHandle<'_, T> { fn push(&mut self, item: T) -> Result<(), T> { let _ = self.queue.queue.push(item); Ok(()) diff --git a/data_structures/stacks/scc_stack/src/main.rs b/data_structures/stacks/scc_stack/src/main.rs new file mode 100644 index 0000000..f407cd9 --- /dev/null +++ b/data_structures/stacks/scc_stack/src/main.rs @@ -0,0 +1,21 @@ +use log::*; +use benchmark_core::benchmarks::fifo_queue_benchmarks::benchmark_fifo_queue; + + +fn main() { + // initialize env_logger if not in silent release mode + #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] + { + env_logger::init(); + debug!("envlogger init"); + } + log::info!("Starting benchmark"); + + match benchmark_fifo_queue::>("scc_stack") { + Ok(_) => println!("Benchmark done."), + Err(e) => { + eprintln!("Benchmark received error: {}", e); + println!("Benchmark exiting due to error."); + } + } +} diff --git a/queues/boost_queue_cpp/src/main.rs b/queues/boost_queue_cpp/src/main.rs deleted file mode 100644 index 16c0533..0000000 --- a/queues/boost_queue_cpp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("boost_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/bounded_concurrent_queue/src/main.rs b/queues/bounded_concurrent_queue/src/main.rs deleted file mode 100644 index a13889d..0000000 --- a/queues/bounded_concurrent_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("bounded_concurrent_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/bounded_ringbuffer/src/main.rs b/queues/bounded_ringbuffer/src/main.rs deleted file mode 100644 index c311094..0000000 --- a/queues/bounded_ringbuffer/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("bounded_ringbuffer") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/faaa_queue/src/main.rs b/queues/faaa_queue/src/main.rs deleted file mode 100644 index 0d39ba8..0000000 --- a/queues/faaa_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("faa_array_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/faaa_queue_cpp/src/main.rs b/queues/faaa_queue_cpp/src/main.rs deleted file mode 100644 index 9dcc863..0000000 --- a/queues/faaa_queue_cpp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("faaa_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lcrq/src/main.rs b/queues/lcrq/src/main.rs deleted file mode 100644 index 7796b9b..0000000 --- a/queues/lcrq/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("array_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lcrq_cpp/src/main.rs b/queues/lcrq_cpp/src/main.rs deleted file mode 100644 index ee5b37e..0000000 --- a/queues/lcrq_cpp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("lcrq_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lf_queue/src/main.rs b/queues/lf_queue/src/main.rs deleted file mode 100644 index 335d4fa..0000000 --- a/queues/lf_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("lf_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lockfree_queue/src/main.rs b/queues/lockfree_queue/src/main.rs deleted file mode 100644 index d4d9470..0000000 --- a/queues/lockfree_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("lockfree_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lprq/src/main.rs b/queues/lprq/src/main.rs deleted file mode 100644 index 3b76232..0000000 --- a/queues/lprq/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("LPRQ") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/lprq_cpp/src/main.rs b/queues/lprq_cpp/src/main.rs deleted file mode 100644 index 5ac4ebf..0000000 --- a/queues/lprq_cpp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("lprq_queue_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/moodycamel_cpp/src/main.rs b/queues/moodycamel_cpp/src/main.rs deleted file mode 100644 index 69814d7..0000000 --- a/queues/moodycamel_cpp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("moodycamel_cpp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/ms_queue/src/main.rs b/queues/ms_queue/src/main.rs deleted file mode 100644 index e8888f3..0000000 --- a/queues/ms_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("ms_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/scc2_queue/src/main.rs b/queues/scc2_queue/src/main.rs deleted file mode 100644 index 79af830..0000000 --- a/queues/scc2_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("scc2_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/scc_queue/src/main.rs b/queues/scc_queue/src/main.rs deleted file mode 100644 index 9ed41de..0000000 --- a/queues/scc_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("scc_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/seg_queue/src/main.rs b/queues/seg_queue/src/main.rs deleted file mode 100644 index 47f72b3..0000000 --- a/queues/seg_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("seg_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/tz_queue_hp/src/main.rs b/queues/tz_queue_hp/src/main.rs deleted file mode 100644 index 53c8ab6..0000000 --- a/queues/tz_queue_hp/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("tz_queue_hp") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/tz_queue_leak/src/main.rs b/queues/tz_queue_leak/src/main.rs deleted file mode 100644 index 584d4df..0000000 --- a/queues/tz_queue_leak/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("tz_queue_leak") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/unbounded_concurrent_queue/src/main.rs b/queues/unbounded_concurrent_queue/src/main.rs deleted file mode 100644 index 7c6d20a..0000000 --- a/queues/unbounded_concurrent_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("unbounded_concurrent_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/queues/wf_queue/src/main.rs b/queues/wf_queue/src/main.rs deleted file mode 100644 index 476a494..0000000 --- a/queues/wf_queue/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("wf_queue") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/readme.md b/readme.md index 3da7f91..5e271b0 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,7 @@ This is a project to benchmark different implementations of queues (currently FIFO, LIFO, bounded or unbounded) to measure their output and performance. # Contents +- [Disclaimer](#disclaimer) - [How to use](#how-to-use) - [Queue implementations](#queue-implementations) - [Benchmarks](#benchmarks) @@ -14,6 +15,10 @@ This is a project to benchmark different implementations of queues (currently FI - [BFS](#bfs) - [Logging](#logging) +## Disclaimer + +This project is currently undergoing a rework. The basic functionality still works but some features don't work as described in this README. Some arguments have been reworked to support other data structures, so the description below is not currently valid. Use the `--help` command to get the up-to-date arguments. Some features don't work for certain data structures, for example, `benchmark_core/memeory_tracking` doesn't work for the priority_queue data structures. The output will also look slightly different, but this is planned to be fixed in the future. + ## How to use: ```bash # Using cargo run @@ -112,7 +117,7 @@ Your queue will have to implement the traits found in `src/traits.rs` so that th /// The required queue trait. pub trait ConcurrentQueue { /// Returns a thread-local handle for the queue. - fn register(&self) -> impl Handle; + fn register(&self) -> impl HandleQueue; /// Returns the name of the queue. fn get_id(&self) -> String; @@ -123,7 +128,7 @@ pub trait ConcurrentQueue { } /// The required queue handle trait. -pub trait Handle { +pub trait HandleQueue { /// Pushes an item to the queue. /// If it fails, returns the item pushed. fn push(&mut self, item: T) -> Result<(), T>; @@ -252,7 +257,7 @@ Now all that is left is to create the Rust queue files. Create `lib.rs` and `mai #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use benchmark_core::traits::{ConcurrentQueue, Handle}; +use benchmark_core::traits::{ConcurrentQueue, HandleQueue}; // Include the generated bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -297,7 +302,7 @@ struct YourQueueHandle<'a,T> { pub q: &'a YourCppQueue } -impl Handle for YourCppQueueHandle<'_,T> { +impl HandleQueue for YourCppQueueHandle<'_,T> { fn push(&mut self, item: T) -> Result<(), T> { let ptr: *mut std::ffi::c_void = Box::::into_raw(Box::new(item)) as *mut std::ffi::c_void; match self.q.push(ptr) { @@ -318,7 +323,7 @@ impl Handle for YourCppQueueHandle<'_,T> { } impl ConcurrentQueue for YourCppQueue { - fn register(&self) -> impl Handle { + fn register(&self) -> impl HandleQueue { YourCppQueueHandle { q: self, } diff --git a/scripts/run_benchmark.sh b/scripts/run_benchmark.sh index 394e1d8..6f28882 100755 --- a/scripts/run_benchmark.sh +++ b/scripts/run_benchmark.sh @@ -1,22 +1,22 @@ #!/bin/bash ./clean.sh -RUST_LOG=debug cargo run --release --features memory_tracking -p basic_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p basic_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p array_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p array_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p lockfree_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p lockfree_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p unbounded_concurrent_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p unbounded_concurrent_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p bounded_ringbuffer -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p bounded_ringbuffer -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p atomic_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p atomic_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p wf_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p wf_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p scc_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p scc_queue -- -t 1 basic -RUST_LOG=debug cargo run --release --features memory_tracking -p scc2_queue -- -t 1 ping-pong -RUST_LOG=debug cargo run --release --features memory_tracking -p scc2_queue -- -t 1 basic +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p basic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p basic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p array_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p array_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p lockfree_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p lockfree_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p unbounded_concurrent_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p unbounded_concurrent_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p bounded_ringbuffer -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p bounded_ringbuffer -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p atomic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p atomic_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p wf_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p wf_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc2_queue -- -t 1 prod-con +RUST_LOG=debug cargo run --release --features benchmark_core/memory_tracking -p scc2_queue -- -t 1 prod-con bat output/* diff --git a/stacks/lockfree_stack/src/main.rs b/stacks/lockfree_stack/src/main.rs deleted file mode 100644 index 620bbb9..0000000 --- a/stacks/lockfree_stack/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("lockfree_stack") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/stacks/scc2_stack/src/main.rs b/stacks/scc2_stack/src/main.rs deleted file mode 100644 index 2a90dbe..0000000 --- a/stacks/scc2_stack/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("scc2_stack") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -} diff --git a/stacks/scc_stack/src/main.rs b/stacks/scc_stack/src/main.rs deleted file mode 100644 index 0f30f6a..0000000 --- a/stacks/scc_stack/src/main.rs +++ /dev/null @@ -1,20 +0,0 @@ -use log::*; - - -fn main() { - // initialize env_logger if not in silent release mode - #[cfg(not(all(not(debug_assertions), feature = "silent-release")))] - { - env_logger::init(); - debug!("envlogger init"); - } - log::info!("Starting benchmark"); - - match benchmark_core::benchmark_target_queue::>("scc_stack") { - Ok(_) => println!("Benchmark done."), - Err(e) => { - eprintln!("Benchmark received error: {}", e); - println!("Benchmark exiting due to error."); - } - } -}