From 8d87b7415e48334aad8fe83db250d449ca58236d Mon Sep 17 00:00:00 2001 From: Trivernis Date: Fri, 3 Apr 2020 11:21:21 +0200 Subject: [PATCH] Export benchmarking stuff to external library --- Cargo.lock | 12 +++- Cargo.toml | 2 +- src/main.rs | 171 +++++----------------------------------------------- 3 files changed, 28 insertions(+), 157 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 134b735..2366eeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,13 +6,23 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "benchlib-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2fbf36bb2cf3eeb3f83dff4d5ba3083f08048173567b0c8a391a55591eb4af" +dependencies = [ + "rayon", + "termion", +] + [[package]] name = "benchmarks" version = "0.1.0" dependencies = [ + "benchlib-rs", "crossbeam-channel", "rayon", - "termion", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 53da006..e2aff78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,4 @@ edition = "2018" [dependencies] rayon = "1.3.0" crossbeam-channel = "0.4.2" -termion = "1.5.5" \ No newline at end of file +benchlib-rs = "0.2.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 93ad6d4..fc9734a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,162 +1,23 @@ #![allow(dead_code)] -use rayon::prelude::*; -use std::fmt::{self, Display}; -use std::time::{Duration, Instant}; -use termion::{color, style}; - -#[derive(Debug, Clone)] -struct DurationDifference { - pub inner: Duration, - pub positive: bool, -} - -#[derive(Debug, Clone)] -struct BenchVec { - pub inner: Vec, -} - -/// A struct that stores a vector of Durations for benchmarks -/// and allows some statistical operations on it -impl BenchVec { - /// Creates a new empty BenchVec - pub fn new() -> Self { - Self { inner: Vec::new() } - } - - /// Creates a BenchVec from an existing vector of Durations - pub fn from_vec(vec: &Vec) -> Self { - Self { inner: vec.clone() } - } - - /// Adds an element to the BenchVec - pub fn push(&mut self, item: Duration) -> &mut Self { - self.inner.push(item); - - self - } - - /// Appends a different BenchVec to this one - pub fn append(&mut self, other: Self) -> &mut Self { - self.inner.append(&mut other.inner.clone()); - - self - } - - /// Returns the length of stored elements - pub fn len(&self) -> usize { - self.inner.len() - } - - /// Returns the sum of all stored elements - pub fn sum(&self) -> Duration { - self.inner.par_iter().sum::() - } - - /// Returns the average of all durations - pub fn average(&self) -> Duration { - self.sum() / self.inner.len() as u32 - } - - /// Returns the standard deviation of all durations - pub fn standard_deviation(&self) -> f64 { - (self.sum().as_nanos() as f64 / (self.len() as f64 - 1f64)).sqrt() - } - - /// Compares two benchmarks by calculating the average - pub fn compare(&self, other: Self) -> DurationDifference { - let avg1 = self.average(); - let avg2 = other.average(); - if avg1 > avg2 { - DurationDifference { - inner: avg1 - avg2, - positive: true, - } - } else { - DurationDifference { - inner: avg2 - avg1, - positive: false, - } - } - } -} - -impl Display for BenchVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let avg_duration = self.average(); - let standard_deviation = self.standard_deviation(); - write!( - f, - "Average Duration: {:?} (±{:.2}ns ~ {:.2}%)", - avg_duration, - standard_deviation, - (standard_deviation / avg_duration.as_nanos() as f64) * 100f64 - ) - } -} - -impl Display for DurationDifference { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}{:?}", - if self.positive { "+" } else { "-" }, - self.inner - ) - } -} - -const BENCHMARK_ITERATIONS: usize = 1000; +use benchlib::benching::Bencher; pub fn main() { - bench_function("Spawn and Stop thread", || to_test::start_stop_thread()); - let mpsc = bench_function("MPSC channel 1000 u128", || to_test::send_mpsc_channel()); - let diff_channels = - bench_function("MPMC channel 1000 u128", || to_test::send_mpmc_channel()).compare(mpsc); - println!("Difference:\t {}", diff_channels); - bench_function("Multiply to 100", || to_test::multiply_to(100)); - let largest_single = bench_function("Largest prime until 10000000", || { - to_test::largest_prime(10000000) - }); - let diff = bench_function("Largest prime parallel until 10000000", || { - to_test::largest_prime_par(10000000) - }) - .compare(largest_single); - println!("Difference:\t {}", diff) -} - -/// Benchmarks a closure a given number of times and returns the -/// average duration as well as all measured durations -fn bench_n_times T>(n: usize, func: F) -> BenchVec { - let mut durations = BenchVec::new(); - for _ in 0..n { - let start = Instant::now(); - func(); - durations.push(start.elapsed()); - } - - durations -} - -/// Benchmarks a closure a specific number of times -/// and reports the results to the commandline -fn bench_function T>(name: &str, func: F) -> BenchVec { - println!( - "\n{}{}{}{}", - color::Fg(color::LightBlue), - style::Bold, - name, - style::Reset - ); - let bench_durations = bench_n_times(BENCHMARK_ITERATIONS, func); - if bench_durations.len() > 10 { - println!("Durations(10):\t {:?}...", &bench_durations.inner[0..10]); - } else { - println!("Durations:\t {:?}", bench_durations.inner); - } - println!("{}", bench_durations); - - bench_durations + let mut bencher = Bencher::new(); + bencher + .set_iterations(10000) + .bench("Multiply to 100", || to_test::multiply_to(100)) + .bench("Spawn and Stop thread", || to_test::start_stop_thread()) + .bench("MPSC channel 1000 u128", || to_test::send_mpsc_channel()) + .bench("MPMC channel 1000 u128", || to_test::send_mpmc_channel()) + .compare() + .bench("Largest prime until 1000000", || { + to_test::largest_prime(1000000) + }) + .bench("Largest prime parallel until 1000000", || { + to_test::largest_prime_par(1000000) + }) + .compare(); } mod to_test {