From 03883c00d606ba0e5d23849852b1aad7be3c1e03 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Sun, 3 Mar 2024 03:56:06 +0800 Subject: [PATCH] dev: repository benchmark uses criterion --- Cargo.lock | 4 +- packages/torrent-repository/Cargo.toml | 8 +- .../benches/helpers/args.rs | 15 -- .../benches/helpers/asyn.rs | 199 ++++++++---------- .../torrent-repository/benches/helpers/mod.rs | 1 - .../benches/helpers/sync.rs | 179 +++++++--------- .../benches/helpers/utils.rs | 33 --- .../benches/repository-benchmark.rs | 187 ---------------- .../benches/repository_benchmark.rs | 191 +++++++++++++++++ 9 files changed, 363 insertions(+), 454 deletions(-) delete mode 100644 packages/torrent-repository/benches/helpers/args.rs delete mode 100644 packages/torrent-repository/benches/repository-benchmark.rs create mode 100644 packages/torrent-repository/benches/repository_benchmark.rs diff --git a/Cargo.lock b/Cargo.lock index 8ec92244..b8437326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -762,6 +762,7 @@ dependencies = [ "ciborium", "clap", "criterion-plot", + "futures", "is-terminal", "itertools 0.10.5", "num-traits", @@ -774,6 +775,7 @@ dependencies = [ "serde_derive", "serde_json", "tinytemplate", + "tokio", "walkdir", ] @@ -3557,7 +3559,7 @@ dependencies = [ name = "torrust-tracker-torrent-repository" version = "3.0.0-alpha.12-develop" dependencies = [ - "clap", + "criterion", "futures", "serde", "tokio", diff --git a/packages/torrent-repository/Cargo.toml b/packages/torrent-repository/Cargo.toml index 0df82a2c..b53b9a15 100644 --- a/packages/torrent-repository/Cargo.toml +++ b/packages/torrent-repository/Cargo.toml @@ -16,9 +16,15 @@ rust-version.workspace = true version.workspace = true [dependencies] -clap = { version = "4.4.8", features = ["derive"] } futures = "0.3.29" tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } torrust-tracker-primitives = { version = "3.0.0-alpha.12-develop", path = "../primitives" } torrust-tracker-configuration = { version = "3.0.0-alpha.12-develop", path = "../configuration" } serde = { version = "1", features = ["derive"] } + +[dev-dependencies] +criterion = { version = "0", features = ["async_tokio"] } + +[[bench]] +harness = false +name = "repository_benchmark" diff --git a/packages/torrent-repository/benches/helpers/args.rs b/packages/torrent-repository/benches/helpers/args.rs deleted file mode 100644 index 3a38c55a..00000000 --- a/packages/torrent-repository/benches/helpers/args.rs +++ /dev/null @@ -1,15 +0,0 @@ -use clap::Parser; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -pub struct Args { - /// Amount of benchmark worker threads - #[arg(short, long)] - pub threads: usize, - /// Amount of time in ns a thread will sleep to simulate a client response after handling a task - #[arg(short, long)] - pub sleep: Option, - /// Compare with old implementations of the torrent repository - #[arg(short, long)] - pub compare: Option, -} diff --git a/packages/torrent-repository/benches/helpers/asyn.rs b/packages/torrent-repository/benches/helpers/asyn.rs index 4fb37104..80f70cdc 100644 --- a/packages/torrent-repository/benches/helpers/asyn.rs +++ b/packages/torrent-repository/benches/helpers/asyn.rs @@ -1,182 +1,155 @@ use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, Instant}; -use clap::Parser; use futures::stream::FuturesUnordered; use torrust_tracker_primitives::info_hash::InfoHash; use torrust_tracker_torrent_repository::repository::RepositoryAsync; -use super::args::Args; -use super::utils::{generate_unique_info_hashes, get_average_and_adjusted_average_from_results, DEFAULT_PEER}; +use super::utils::{generate_unique_info_hashes, DEFAULT_PEER}; -pub async fn add_one_torrent(samples: usize) -> (Duration, Duration) +pub async fn add_one_torrent(samples: u64) -> Duration where V: RepositoryAsync + Default, { - let mut results: Vec = Vec::with_capacity(samples); + let start = Instant::now(); for _ in 0..samples { let torrent_repository = V::default(); let info_hash = InfoHash([0; 20]); - let start_time = std::time::Instant::now(); - torrent_repository .update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER) .await; - - let result = start_time.elapsed(); - - results.push(result); } - get_average_and_adjusted_average_from_results(results) + start.elapsed() } // Add one torrent ten thousand times in parallel (depending on the set worker threads) -pub async fn update_one_torrent_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn update_one_torrent_in_parallel(runtime: &tokio::runtime::Runtime, samples: u64, sleep: Option) -> Duration where V: RepositoryAsync + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hash: &'static InfoHash = &InfoHash([0; 20]); - let handles = FuturesUnordered::new(); - - // Add the torrent/peer to the torrent repository - torrent_repository - .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) - .await; + let torrent_repository = Arc::::default(); + let info_hash: &'static InfoHash = &InfoHash([0; 20]); + let handles = FuturesUnordered::new(); - let start_time = std::time::Instant::now(); + // Add the torrent/peer to the torrent repository + torrent_repository + .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) + .await; - for _ in 0..10_000 { - let torrent_repository_clone = torrent_repository.clone(); + let start = Instant::now(); - let handle = runtime.spawn(async move { - torrent_repository_clone - .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) - .await; - - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); - - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); + for _ in 0..samples { + let torrent_repository_clone = torrent_repository.clone(); - handles.push(handle); - } + let handle = runtime.spawn(async move { + torrent_repository_clone + .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) + .await; - // Await all tasks - futures::future::join_all(handles).await; + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - let result = start_time.elapsed(); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } // Add ten thousand torrents in parallel (depending on the set worker threads) -pub async fn add_multiple_torrents_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn add_multiple_torrents_in_parallel( + runtime: &tokio::runtime::Runtime, + samples: u64, + sleep: Option, +) -> Duration where V: RepositoryAsync + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hashes = generate_unique_info_hashes(10_000); - let handles = FuturesUnordered::new(); - - let start_time = std::time::Instant::now(); + let torrent_repository = Arc::::default(); + let info_hashes = generate_unique_info_hashes(samples.try_into().expect("it should fit in a usize")); + let handles = FuturesUnordered::new(); - for info_hash in info_hashes { - let torrent_repository_clone = torrent_repository.clone(); + let start = Instant::now(); - let handle = runtime.spawn(async move { - torrent_repository_clone - .update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER) - .await; + for info_hash in info_hashes { + let torrent_repository_clone = torrent_repository.clone(); - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); - - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); - - handles.push(handle); - } + let handle = runtime.spawn(async move { + torrent_repository_clone + .update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER) + .await; - // Await all tasks - futures::future::join_all(handles).await; + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - let result = start_time.elapsed(); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } // Async update ten thousand torrents in parallel (depending on the set worker threads) -pub async fn update_multiple_torrents_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn update_multiple_torrents_in_parallel( + runtime: &tokio::runtime::Runtime, + samples: u64, + sleep: Option, +) -> Duration where V: RepositoryAsync + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hashes = generate_unique_info_hashes(10_000); - let handles = FuturesUnordered::new(); - - // Add the torrents/peers to the torrent repository - for info_hash in &info_hashes { - torrent_repository - .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) - .await; - } + let torrent_repository = Arc::::default(); + let info_hashes = generate_unique_info_hashes(samples.try_into().expect("it should fit in usize")); + let handles = FuturesUnordered::new(); - let start_time = std::time::Instant::now(); - - for info_hash in info_hashes { - let torrent_repository_clone = torrent_repository.clone(); - - let handle = runtime.spawn(async move { - torrent_repository_clone - .update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER) - .await; + // Add the torrents/peers to the torrent repository + for info_hash in &info_hashes { + torrent_repository + .update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER) + .await; + } - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); + let start = Instant::now(); - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); + for info_hash in info_hashes { + let torrent_repository_clone = torrent_repository.clone(); - handles.push(handle); - } + let handle = runtime.spawn(async move { + torrent_repository_clone + .update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER) + .await; - // Await all tasks - futures::future::join_all(handles).await; + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - let result = start_time.elapsed(); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } diff --git a/packages/torrent-repository/benches/helpers/mod.rs b/packages/torrent-repository/benches/helpers/mod.rs index 758c123b..1026aa4b 100644 --- a/packages/torrent-repository/benches/helpers/mod.rs +++ b/packages/torrent-repository/benches/helpers/mod.rs @@ -1,4 +1,3 @@ -pub mod args; pub mod asyn; pub mod sync; pub mod utils; diff --git a/packages/torrent-repository/benches/helpers/sync.rs b/packages/torrent-repository/benches/helpers/sync.rs index aa2f8188..0523f414 100644 --- a/packages/torrent-repository/benches/helpers/sync.rs +++ b/packages/torrent-repository/benches/helpers/sync.rs @@ -1,172 +1,145 @@ use std::sync::Arc; -use std::time::Duration; +use std::time::{Duration, Instant}; -use clap::Parser; use futures::stream::FuturesUnordered; use torrust_tracker_primitives::info_hash::InfoHash; use torrust_tracker_torrent_repository::repository::Repository; -use super::args::Args; -use super::utils::{generate_unique_info_hashes, get_average_and_adjusted_average_from_results, DEFAULT_PEER}; +use super::utils::{generate_unique_info_hashes, DEFAULT_PEER}; // Simply add one torrent #[must_use] -pub fn add_one_torrent(samples: usize) -> (Duration, Duration) +pub fn add_one_torrent(samples: u64) -> Duration where V: Repository + Default, { - let mut results: Vec = Vec::with_capacity(samples); + let start = Instant::now(); for _ in 0..samples { let torrent_repository = V::default(); let info_hash = InfoHash([0; 20]); - let start_time = std::time::Instant::now(); - torrent_repository.update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER); - - let result = start_time.elapsed(); - - results.push(result); } - get_average_and_adjusted_average_from_results(results) + start.elapsed() } // Add one torrent ten thousand times in parallel (depending on the set worker threads) -pub async fn update_one_torrent_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn update_one_torrent_in_parallel(runtime: &tokio::runtime::Runtime, samples: u64, sleep: Option) -> Duration where V: Repository + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hash: &'static InfoHash = &InfoHash([0; 20]); - let handles = FuturesUnordered::new(); - - // Add the torrent/peer to the torrent repository - torrent_repository.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); + let torrent_repository = Arc::::default(); + let info_hash: &'static InfoHash = &InfoHash([0; 20]); + let handles = FuturesUnordered::new(); - let start_time = std::time::Instant::now(); + // Add the torrent/peer to the torrent repository + torrent_repository.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); - for _ in 0..10_000 { - let torrent_repository_clone = torrent_repository.clone(); + let start = Instant::now(); - let handle = runtime.spawn(async move { - torrent_repository_clone.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); - - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); - - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); + for _ in 0..samples { + let torrent_repository_clone = torrent_repository.clone(); - handles.push(handle); - } + let handle = runtime.spawn(async move { + torrent_repository_clone.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); - // Await all tasks - futures::future::join_all(handles).await; + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - let result = start_time.elapsed(); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } // Add ten thousand torrents in parallel (depending on the set worker threads) -pub async fn add_multiple_torrents_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn add_multiple_torrents_in_parallel( + runtime: &tokio::runtime::Runtime, + samples: u64, + sleep: Option, +) -> Duration where V: Repository + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hashes = generate_unique_info_hashes(10_000); - let handles = FuturesUnordered::new(); + let torrent_repository = Arc::::default(); + let info_hashes = generate_unique_info_hashes(samples.try_into().expect("it should fit in a usize")); + let handles = FuturesUnordered::new(); - let start_time = std::time::Instant::now(); + let start = Instant::now(); - for info_hash in info_hashes { - let torrent_repository_clone = torrent_repository.clone(); + for info_hash in info_hashes { + let torrent_repository_clone = torrent_repository.clone(); - let handle = runtime.spawn(async move { - torrent_repository_clone.update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER); + let handle = runtime.spawn(async move { + torrent_repository_clone.update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER); - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - handles.push(handle); - } - - // Await all tasks - futures::future::join_all(handles).await; - - let result = start_time.elapsed(); - - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } // Update ten thousand torrents in parallel (depending on the set worker threads) -pub async fn update_multiple_torrents_in_parallel(runtime: &tokio::runtime::Runtime, samples: usize) -> (Duration, Duration) +pub async fn update_multiple_torrents_in_parallel( + runtime: &tokio::runtime::Runtime, + samples: u64, + sleep: Option, +) -> Duration where V: Repository + Default, Arc: Clone + Send + Sync + 'static, { - let args = Args::parse(); - let mut results: Vec = Vec::with_capacity(samples); - - for _ in 0..samples { - let torrent_repository = Arc::::default(); - let info_hashes = generate_unique_info_hashes(10_000); - let handles = FuturesUnordered::new(); + let torrent_repository = Arc::::default(); + let info_hashes = generate_unique_info_hashes(samples.try_into().expect("it should fit in usize")); + let handles = FuturesUnordered::new(); - // Add the torrents/peers to the torrent repository - for info_hash in &info_hashes { - torrent_repository.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); - } - - let start_time = std::time::Instant::now(); - - for info_hash in info_hashes { - let torrent_repository_clone = torrent_repository.clone(); - - let handle = runtime.spawn(async move { - torrent_repository_clone.update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER); + // Add the torrents/peers to the torrent repository + for info_hash in &info_hashes { + torrent_repository.update_torrent_with_peer_and_get_stats(info_hash, &DEFAULT_PEER); + } - if let Some(sleep_time) = args.sleep { - let start_time = std::time::Instant::now(); + let start = Instant::now(); - while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} - } - }); + for info_hash in info_hashes { + let torrent_repository_clone = torrent_repository.clone(); - handles.push(handle); - } + let handle = runtime.spawn(async move { + torrent_repository_clone.update_torrent_with_peer_and_get_stats(&info_hash, &DEFAULT_PEER); - // Await all tasks - futures::future::join_all(handles).await; + if let Some(sleep_time) = sleep { + let start_time = std::time::Instant::now(); - let result = start_time.elapsed(); + while start_time.elapsed().as_nanos() < u128::from(sleep_time) {} + } + }); - results.push(result); + handles.push(handle); } - get_average_and_adjusted_average_from_results(results) + // Await all tasks + futures::future::join_all(handles).await; + + start.elapsed() } diff --git a/packages/torrent-repository/benches/helpers/utils.rs b/packages/torrent-repository/benches/helpers/utils.rs index aed9f40c..17019480 100644 --- a/packages/torrent-repository/benches/helpers/utils.rs +++ b/packages/torrent-repository/benches/helpers/utils.rs @@ -1,6 +1,5 @@ use std::collections::HashSet; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::time::Duration; use torrust_tracker_primitives::announce_event::AnnounceEvent; use torrust_tracker_primitives::info_hash::InfoHash; @@ -39,35 +38,3 @@ pub fn generate_unique_info_hashes(size: usize) -> Vec { result.into_iter().collect() } - -#[must_use] -pub fn within_acceptable_range(test: &Duration, norm: &Duration) -> bool { - let test_secs = test.as_secs_f64(); - let norm_secs = norm.as_secs_f64(); - - // Calculate the upper and lower bounds for the 10% tolerance - let tolerance = norm_secs * 0.1; - - // Calculate the upper and lower limits - let upper_limit = norm_secs + tolerance; - let lower_limit = norm_secs - tolerance; - - test_secs < upper_limit && test_secs > lower_limit -} - -#[must_use] -pub fn get_average_and_adjusted_average_from_results(mut results: Vec) -> (Duration, Duration) { - #[allow(clippy::cast_possible_truncation)] - let average = results.iter().sum::() / results.len() as u32; - - results.retain(|result| within_acceptable_range(result, &average)); - - let mut adjusted_average = Duration::from_nanos(0); - - #[allow(clippy::cast_possible_truncation)] - if results.len() > 1 { - adjusted_average = results.iter().sum::() / results.len() as u32; - } - - (average, adjusted_average) -} diff --git a/packages/torrent-repository/benches/repository-benchmark.rs b/packages/torrent-repository/benches/repository-benchmark.rs deleted file mode 100644 index bff34b25..00000000 --- a/packages/torrent-repository/benches/repository-benchmark.rs +++ /dev/null @@ -1,187 +0,0 @@ -mod helpers; - -use clap::Parser; -use torrust_tracker_torrent_repository::{ - TorrentsRwLockStd, TorrentsRwLockStdMutexStd, TorrentsRwLockStdMutexTokio, TorrentsRwLockTokio, TorrentsRwLockTokioMutexStd, - TorrentsRwLockTokioMutexTokio, -}; - -use crate::helpers::args::Args; -use crate::helpers::{asyn, sync}; - -#[allow(clippy::too_many_lines)] -#[allow(clippy::print_literal)] -fn main() { - let args = Args::parse(); - - // Add 1 to worker_threads since we need a thread that awaits the benchmark - let rt = tokio::runtime::Builder::new_multi_thread() - .worker_threads(args.threads + 1) - .enable_time() - .build() - .unwrap(); - - println!("TorrentsRwLockTokio"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - rt.block_on(asyn::add_one_torrent::(1_000_000)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(asyn::update_one_torrent_in_parallel::(&rt, 10)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(asyn::add_multiple_torrents_in_parallel::(&rt, 10)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(asyn::update_multiple_torrents_in_parallel::(&rt, 10)) - ); - - if let Some(true) = args.compare { - println!(); - - println!("TorrentsRwLockStd"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - sync::add_one_torrent::(1_000_000) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(sync::update_one_torrent_in_parallel::(&rt, 10)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(sync::add_multiple_torrents_in_parallel::(&rt, 10)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(sync::update_multiple_torrents_in_parallel::(&rt, 10)) - ); - - println!(); - - println!("TorrentsRwLockStdMutexStd"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - sync::add_one_torrent::(1_000_000) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(sync::update_one_torrent_in_parallel::(&rt, 10)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(sync::add_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(sync::update_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - - println!(); - - println!("TorrentsRwLockStdMutexTokio"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - rt.block_on(asyn::add_one_torrent::(1_000_000)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(asyn::update_one_torrent_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(asyn::add_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(asyn::update_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - - println!(); - - println!("TorrentsRwLockTokioMutexStd"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - rt.block_on(asyn::add_one_torrent::(1_000_000)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(asyn::update_one_torrent_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(asyn::add_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(asyn::update_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - - println!(); - - println!("TorrentsRwLockTokioMutexTokio"); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_one_torrent", - rt.block_on(asyn::add_one_torrent::(1_000_000)) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_one_torrent_in_parallel", - rt.block_on(asyn::update_one_torrent_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "add_multiple_torrents_in_parallel", - rt.block_on(asyn::add_multiple_torrents_in_parallel::( - &rt, 10 - )) - ); - println!( - "{}: Avg/AdjAvg: {:?}", - "update_multiple_torrents_in_parallel", - rt.block_on(asyn::update_multiple_torrents_in_parallel::(&rt, 10)) - ); - } -} diff --git a/packages/torrent-repository/benches/repository_benchmark.rs b/packages/torrent-repository/benches/repository_benchmark.rs new file mode 100644 index 00000000..a3684c8e --- /dev/null +++ b/packages/torrent-repository/benches/repository_benchmark.rs @@ -0,0 +1,191 @@ +use std::time::Duration; + +mod helpers; + +use criterion::{criterion_group, criterion_main, Criterion}; +use torrust_tracker_torrent_repository::{ + TorrentsRwLockStd, TorrentsRwLockStdMutexStd, TorrentsRwLockStdMutexTokio, TorrentsRwLockTokio, TorrentsRwLockTokioMutexStd, + TorrentsRwLockTokioMutexTokio, +}; + +use crate::helpers::{asyn, sync}; + +fn add_one_torrent(c: &mut Criterion) { + let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(4).build().unwrap(); + + let mut group = c.benchmark_group("add_one_torrent"); + + group.warm_up_time(Duration::from_millis(500)); + group.measurement_time(Duration::from_millis(1000)); + + group.bench_function("RwLockStd", |b| { + b.iter_custom(sync::add_one_torrent::); + }); + + group.bench_function("RwLockStdMutexStd", |b| { + b.iter_custom(sync::add_one_torrent::); + }); + + group.bench_function("RwLockStdMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(asyn::add_one_torrent::); + }); + + group.bench_function("RwLockTokio", |b| { + b.to_async(&rt).iter_custom(asyn::add_one_torrent::); + }); + + group.bench_function("RwLockTokioMutexStd", |b| { + b.to_async(&rt) + .iter_custom(asyn::add_one_torrent::); + }); + + group.bench_function("RwLockTokioMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(asyn::add_one_torrent::); + }); + + group.finish(); +} + +fn add_multiple_torrents_in_parallel(c: &mut Criterion) { + let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(4).build().unwrap(); + + let mut group = c.benchmark_group("add_multiple_torrents_in_parallel"); + + //group.sampling_mode(criterion::SamplingMode::Flat); + //group.sample_size(10); + + group.warm_up_time(Duration::from_millis(500)); + group.measurement_time(Duration::from_millis(1000)); + + group.bench_function("RwLockStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::add_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.finish(); +} + +fn update_one_torrent_in_parallel(c: &mut Criterion) { + let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(4).build().unwrap(); + + let mut group = c.benchmark_group("update_one_torrent_in_parallel"); + + //group.sampling_mode(criterion::SamplingMode::Flat); + //group.sample_size(10); + + group.warm_up_time(Duration::from_millis(500)); + group.measurement_time(Duration::from_millis(1000)); + + group.bench_function("RwLockStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_one_torrent_in_parallel::(&rt, iters, None)); + }); + + group.finish(); +} + +fn update_multiple_torrents_in_parallel(c: &mut Criterion) { + let rt = tokio::runtime::Builder::new_multi_thread().worker_threads(4).build().unwrap(); + + let mut group = c.benchmark_group("update_multiple_torrents_in_parallel"); + + //group.sampling_mode(criterion::SamplingMode::Flat); + //group.sample_size(10); + + group.warm_up_time(Duration::from_millis(500)); + group.measurement_time(Duration::from_millis(1000)); + + group.bench_function("RwLockStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::update_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| sync::update_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockStdMutexTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokio", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexStd", |b| { + b.to_async(&rt) + .iter_custom(|iters| asyn::update_multiple_torrents_in_parallel::(&rt, iters, None)); + }); + + group.bench_function("RwLockTokioMutexTokio", |b| { + b.to_async(&rt).iter_custom(|iters| { + asyn::update_multiple_torrents_in_parallel::(&rt, iters, None) + }); + }); + + group.finish(); +} + +criterion_group!( + benches, + add_one_torrent, + add_multiple_torrents_in_parallel, + update_one_torrent_in_parallel, + update_multiple_torrents_in_parallel +); +criterion_main!(benches);