Export benchmarking stuff to external library

master
Trivernis 5 years ago
parent d88062dc6d
commit 8d87b7415e

12
Cargo.lock generated

@ -6,13 +6,23 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 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]] [[package]]
name = "benchmarks" name = "benchmarks"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"benchlib-rs",
"crossbeam-channel", "crossbeam-channel",
"rayon", "rayon",
"termion",
] ]
[[package]] [[package]]

@ -9,4 +9,4 @@ edition = "2018"
[dependencies] [dependencies]
rayon = "1.3.0" rayon = "1.3.0"
crossbeam-channel = "0.4.2" crossbeam-channel = "0.4.2"
termion = "1.5.5" benchlib-rs = "0.2.0"

@ -1,162 +1,23 @@
#![allow(dead_code)] #![allow(dead_code)]
use rayon::prelude::*; use benchlib::benching::Bencher;
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<Duration>,
}
/// 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<Duration>) -> 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::<Duration>()
}
/// 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;
pub fn main() { pub fn main() {
bench_function("Spawn and Stop thread", || to_test::start_stop_thread()); let mut bencher = Bencher::new();
let mpsc = bench_function("MPSC channel 1000 u128", || to_test::send_mpsc_channel()); bencher
let diff_channels = .set_iterations(10000)
bench_function("MPMC channel 1000 u128", || to_test::send_mpmc_channel()).compare(mpsc); .bench("Multiply to 100", || to_test::multiply_to(100))
println!("Difference:\t {}", diff_channels); .bench("Spawn and Stop thread", || to_test::start_stop_thread())
bench_function("Multiply to 100", || to_test::multiply_to(100)); .bench("MPSC channel 1000 u128", || to_test::send_mpsc_channel())
let largest_single = bench_function("Largest prime until 10000000", || { .bench("MPMC channel 1000 u128", || to_test::send_mpmc_channel())
to_test::largest_prime(10000000) .compare()
}); .bench("Largest prime until 1000000", || {
let diff = bench_function("Largest prime parallel until 10000000", || { to_test::largest_prime(1000000)
to_test::largest_prime_par(10000000)
}) })
.compare(largest_single); .bench("Largest prime parallel until 1000000", || {
println!("Difference:\t {}", diff) to_test::largest_prime_par(1000000)
} })
.compare();
/// Benchmarks a closure a given number of times and returns the
/// average duration as well as all measured durations
fn bench_n_times<T, F: Fn() -> 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, F: Fn() -> 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
} }
mod to_test { mod to_test {

Loading…
Cancel
Save