Factored benchmarks apart in a reasonable way.

This commit is contained in:
Stu Black 2018-12-27 01:41:34 -05:00
parent 227e2c548e
commit fa353df41a
14 changed files with 506 additions and 378 deletions

View File

@ -5,9 +5,69 @@ authors = ["Donald S. Black <trurl@freeshell.org>"]
edition = "2018"
[dev_dependencies]
criterion = "0.1.2"
rand = "0.3"
rand = "0.6.1"
[features]
default = []
benchmark-definitions = ["criterion", "rand", "num-bigint"]
# Build with "cargo bench --features=benchmark-definitions".
[profile.bench]
opt-level = 3
debug = false
rpath = false
debug-assertions = false
lto = true
[dependencies.criterion]
version = "0.2.4"
optional = true
[dependencies.rand]
version = "0.6.1"
optional = true
[dependencies.num-bigint]
version = "0.2.2"
optional = true
features = ["rand"]
[[bench]]
name = "bench"
name = "tiny-i32-sort-binary"
path = "benches/tiny_i32_sort_binary.rs"
harness = false
[[bench]]
name = "tiny-i32-sort-weak"
path = "benches/tiny_i32_sort_weak.rs"
harness = false
[[bench]]
name = "tiny-i128-sort-binary"
path = "benches/tiny_i128_sort_binary.rs"
harness = false
[[bench]]
name = "tiny-i128-sort-weak"
path = "benches/tiny_i128_sort_weak.rs"
harness = false
[[bench]]
name = "tiny-u32768-sort-binary"
path = "benches/tiny_u32768_sort_binary.rs"
harness = false
[[bench]]
name = "tiny-u32768-sort-weak"
path = "benches/tiny_u32768_sort_weak.rs"
harness = false
# [[bench]]
# name = "small"
# path = "benches/small.rs"
# harness = false
# [[bench]]
# name = "medium"
# path = "benches/medium.rs"
# harness = false

View File

@ -1,373 +0,0 @@
#[macro_use] extern crate criterion;
extern crate rand;
extern crate weak_heap;
use criterion::Criterion;
use rand::{Rng, SeedableRng, StdRng};
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::collections::{BinaryHeap, HashMap};
use std::mem;
use std::ops::Add;
use std::sync::atomic;
use weak_heap::WeakHeap;
static TINY_SIZES: &[usize] = &[1, 2, 7, 8, 9, 10, 20, 30, 31, 32, 33];
// static SMALL_SIZES: &[usize] = &[100, 127, 128, 129, 150, 200, 254, 255, 256, 257, 258];
// static MEDIUM_SIZES: &[usize] = &[10000, 20000, 32767, 32768, 32769, 50000];
// static LARGE_SIZES: &[usize] = &[1048575, 1048576, 1048577];
#[derive(Clone, Copy, Debug)]
struct ComparisonCountedI32(i32);
static PARTIAL_ORD_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl PartialOrd for ComparisonCountedI32 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PARTIAL_ORD_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.partial_cmp(&other.0)
}
}
static ORD_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl Ord for ComparisonCountedI32 {
fn cmp(&self, other: &Self) -> Ordering {
ORD_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.cmp(&other.0)
}
}
static PARTIAL_EQ_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
static PARTIAL_NEQ_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl PartialEq for ComparisonCountedI32 {
fn eq(&self, other: &Self) -> bool {
PARTIAL_EQ_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.eq(&other.0)
}
fn ne(&self, other: &Self) -> bool {
PARTIAL_NEQ_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.ne(&other.0)
}
}
impl Eq for ComparisonCountedI32 {}
impl From<i32> for ComparisonCountedI32 {
fn from(x: i32) -> Self {
ComparisonCountedI32(x)
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
struct ComparisonCounts {
partial_ord: usize,
ord: usize,
eq: usize,
neq: usize,
}
impl ComparisonCounts {
fn now() -> Self {
ComparisonCounts {
partial_ord: PARTIAL_ORD_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
ord: ORD_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
eq: PARTIAL_EQ_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
neq: PARTIAL_NEQ_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
}
}
fn take_difference(&mut self) {
let mut now = ComparisonCounts::now();
assert!(now.partial_ord >= self.partial_ord);
now.partial_ord -= self.partial_ord;
assert!(now.ord >= self.ord);
now.ord -= self.ord;
assert!(now.eq >= self.eq);
now.eq -= self.eq;
assert!(now.neq >= self.neq);
now.neq -= self.neq;
mem::swap(&mut now, self);
}
}
impl Add for ComparisonCounts {
type Output = Self;
fn add(self, rhs: Self) -> Self {
ComparisonCounts {
partial_ord: self.partial_ord + rhs.partial_ord,
ord: self.ord + rhs.ord,
eq: self.eq + rhs.eq,
neq: self.neq + rhs.neq,
}
}
}
pub fn get_values(size: usize) -> Vec<i32> {
let seed: &[_] = &[1, 2, 3, 4];
let mut rng: StdRng = SeedableRng::from_seed(seed);
(0..size).map(|_| rng.gen::<i32>()).map(|x| x.into()).collect()
}
macro_rules! do_bench {
($bencher: ident, $heap_factory: expr, $sizes: ident) => ({
let sizes = $sizes;
let mut all_values = HashMap::new();
let mut all_sorted = HashMap::new();
for size in sizes {
let values: Vec<ComparisonCountedI32> =
get_values(*size).into_iter().map(|x| x.into()).collect();
let sorted = {
let mut v = values.clone();
v.sort_by(|x, y| y.cmp(x));
v
};
all_values.insert(*size, values);
all_sorted.insert(*size, sorted);
}
$bencher.bench_function_over_inputs(
&format!("sort {}", stringify!($heap_factory)),
|b: &mut criterion::Bencher, &&size: &&usize| {
let mut all_counts = Vec::new();
let mut iterations = 0;
let values = all_values.get(&size).unwrap();
let sorted = all_sorted.get(&size).unwrap();
b.iter(|| {
iterations += 1;
let mut counts = ComparisonCounts::now();
let mut heap = $heap_factory();
for v in values {
heap.push(*v);
}
let mut heap_sorted = Vec::with_capacity(heap.len());
while let Some(x) = heap.pop() {
heap_sorted.push(x);
}
counts.take_difference();
all_counts.push(counts);
assert_eq!(heap_sorted, *sorted);
});
let total_counts = all_counts.into_iter().fold(
ComparisonCounts::default(), |acc, x| acc + x);
// println!("\ndo_bench({}, {}) partial_ord {:.2}, ord {:.2}, eq {:.2}, ne {:.2}",
// stringify!($heap_factory), size,
// (total_counts.partial_ord as f32) / ((size * iterations) as f32),
// (total_counts.ord as f32) / ((size * iterations) as f32),
// (total_counts.eq as f32) / ((size * iterations) as f32),
// (total_counts.neq as f32) / ((size * iterations) as f32));
}, sizes);
})
}
fn bench_tiny(c: &mut Criterion) {
do_bench!(c, BinaryHeap::new, TINY_SIZES);
do_bench!(c, WeakHeap::new, TINY_SIZES);
}
// macro_rules! do_bench_inserts {
// ($bencher: ident, $heap_factory: expr, $size: expr) => ({
// let size: usize = $size;
// let values: Vec<ComparisonCountedI32> =
// get_values(size).into_iter().map(|x| x.into()).collect();
// let mut all_counts = Vec::new();
// let mut iterations = 0;
// $bencher.iter(|| {
// iterations += 1;
// let mut counts = ComparisonCounts::now();
// let mut heap = $heap_factory();
// for v in &values {
// heap.push(*v);
// }
// counts.take_difference();
// all_counts.push(counts);
// });
// let total_counts = all_counts.into_iter().fold(
// ComparisonCounts::default(), |acc, x| acc + x);
// println!("\ndo_bench_inserts({}, {}) partial_ord {:.2}, ord {:.2}, eq {:.2}, ne {:.2}",
// stringify!($heap_factory), size,
// (total_counts.partial_ord as f32) / ((size * iterations) as f32),
// (total_counts.ord as f32) / ((size * iterations) as f32),
// (total_counts.eq as f32) / ((size * iterations) as f32),
// (total_counts.neq as f32) / ((size * iterations) as f32));
// total_counts
// })
// }
// macro_rules! do_bench_removals {
// ($bencher: ident, $heap_factory: expr, $size: expr) => ({
// let size: usize = $size;
// let values: Vec<ComparisonCountedI32> =
// get_values(size).into_iter().map(|x| x.into()).collect();
// let sorted = {
// let mut v = values.clone();
// v.sort_by(|x, y| y.cmp(x));
// v
// };
// let mut all_counts = Vec::new();
// let mut iterations = 0;
// $bencher.iter(|| {
// iterations += 1;
// let mut heap = $heap_factory();
// for v in &values {
// heap.push(*v);
// }
// let mut receptacle = Vec::with_capacity(size);
// let mut counts = ComparisonCounts::now();
// while let Some(x) = heap.pop() {
// receptacle.push(x);
// }
// counts.take_difference();
// assert_eq!(receptacle, sorted);
// all_counts.push(counts);
// });
// let total_counts = all_counts.into_iter().fold(
// ComparisonCounts::default(), |acc, x| acc + x);
// println!("\ndo_bench_removals({}, {}) partial_ord {:.2}, ord {:.2}, eq {:.2}, ne {:.2}",
// stringify!($heap_factory), size,
// (total_counts.partial_ord as f32) / ((size * iterations) as f32),
// (total_counts.ord as f32) / ((size * iterations) as f32),
// (total_counts.eq as f32) / ((size * iterations) as f32),
// (total_counts.neq as f32) / ((size * iterations) as f32));
// total_counts
// })
// }
// fn bench_01_weak_small(c: &mut Criterion) {
// // for size in SMALL_SIZES {
// do_bench!(c, WeakHeap::new, 128);
// // }
// }
// fn bench_02_weak_medium(c: &mut Criterion) {
// // for size in MEDIUM_SIZES {
// do_bench!(c, WeakHeap::new, 32768);
// // }
// }
// fn bench_03_weak_large(c: &mut Criterion) {
// // for size in LARGE_SIZES {
// do_bench!(c, WeakHeap::new, 1048576);
// // }
// }
// fn bench_inserts_00_weak_tiny(c: &mut Criterion) {
// for size in TINY_SIZES {
// do_bench_inserts!(c, WeakHeap::new, *size);
// }
// }
// fn bench_inserts_01_weak_small(c: &mut Criterion) {
// for size in SMALL_SIZES {
// do_bench_inserts!(c, WeakHeap::new, *size);
// }
// }
// fn bench_inserts_02_weak_medium(c: &mut Criterion) {
// for size in MEDIUM_SIZES {
// do_bench_inserts!(c, WeakHeap::new, *size);
// }
// }
// fn bench_inserts_03_weak_large(c: &mut Criterion) {
// for size in LARGE_SIZES {
// do_bench_inserts!(c, WeakHeap::new, *size);
// }
// }
// fn bench_removals_00_weak_tiny(c: &mut Criterion) {
// for size in TINY_SIZES {
// do_bench_removals!(c, WeakHeap::new, *size);
// }
// }
// fn bench_removals_01_weak_small(c: &mut Criterion) {
// for size in SMALL_SIZES {
// do_bench_removals!(c, WeakHeap::new, *size);
// }
// }
// fn bench_removals_02_weak_medium(c: &mut Criterion) {
// for size in MEDIUM_SIZES {
// do_bench_removals!(c, WeakHeap::new, *size);
// }
// }
// fn bench_removals_03_weak_large(c: &mut Criterion) {
// for size in LARGE_SIZES {
// do_bench_removals!(c, WeakHeap::new, *size);
// }
// }
// fn bench_01_builtin_small(c: &mut Criterion) {
// // for size in SMALL_SIZES {
// do_bench!(c, BinaryHeap::new, 128);
// // }
// }
// fn bench_02_builtin_medium(c: &mut Criterion) {
// // for size in MEDIUM_SIZES {
// do_bench!(c, BinaryHeap::new, 32768);
// // }
// }
// fn bench_03_builtin_large(c: &mut Criterion) {
// // for size in LARGE_SIZES {
// do_bench!(c, BinaryHeap::new, 1048576);
// // }
// }
// fn bench_inserts_00_binary_tiny(c: &mut Criterion) {
// for size in TINY_SIZES {
// do_bench_inserts!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_inserts_01_binary_small(c: &mut Criterion) {
// for size in SMALL_SIZES {
// do_bench_inserts!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_inserts_02_binary_medium(c: &mut Criterion) {
// for size in MEDIUM_SIZES {
// do_bench_inserts!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_inserts_03_builtin_large(c: &mut Criterion) {
// for size in LARGE_SIZES {
// do_bench_inserts!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_removals_00_binary_tiny(c: &mut Criterion) {
// for size in TINY_SIZES {
// do_bench_removals!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_removals_01_binary_small(c: &mut Criterion) {
// for size in SMALL_SIZES {
// do_bench_removals!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_removals_02_binary_medium(c: &mut Criterion) {
// for size in MEDIUM_SIZES {
// do_bench_removals!(c, BinaryHeap::new, *size);
// }
// }
// fn bench_removals_03_builtin_large(c: &mut Criterion) {
// for size in LARGE_SIZES {
// do_bench_removals!(c, BinaryHeap::new, *size);
// }
// }
criterion_group!(tiny, bench_tiny);
// criterion_group!(small, bench_01_builtin_small, bench_01_weak_small);
// criterion_group!(medium, bench_02_builtin_medium, bench_02_weak_medium);
// criterion_group!(large, bench_03_builtin_large, bench_03_weak_large);
criterion_main!(tiny);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::i128_sort_binary);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::i128_sort_weak);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::i32_sort_binary);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::i32_sort_weak);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::u32768_sort_binary);

View File

@ -0,0 +1,4 @@
use criterion::criterion_main;
use weak_heap::benches::tiny;
criterion_main!(tiny::u32768_sort_weak);

259
src/benches.rs Normal file
View File

@ -0,0 +1,259 @@
use num_bigint::{BigUint, ToBigUint};
use rand::{Rng, SeedableRng};
use rand::distributions::Standard;
use rand::rngs::StdRng;
use rand::distributions::Distribution;
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::mem;
use std::ops::Add;
use std::sync::atomic;
#[derive(Clone, Copy, Debug)]
pub struct ComparisonCountedI32(i32);
static PARTIAL_ORD_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl PartialOrd for ComparisonCountedI32 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PARTIAL_ORD_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.partial_cmp(&other.0)
}
}
static ORD_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl Ord for ComparisonCountedI32 {
fn cmp(&self, other: &Self) -> Ordering {
ORD_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.cmp(&other.0)
}
}
static PARTIAL_EQ_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
static PARTIAL_NEQ_COMPARISON_COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
impl PartialEq for ComparisonCountedI32 {
fn eq(&self, other: &Self) -> bool {
PARTIAL_EQ_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.eq(&other.0)
}
fn ne(&self, other: &Self) -> bool {
PARTIAL_NEQ_COMPARISON_COUNTER.fetch_add(1, atomic::Ordering::SeqCst);
self.0.ne(&other.0)
}
}
impl Eq for ComparisonCountedI32 {}
impl From<i32> for ComparisonCountedI32 {
fn from(x: i32) -> Self {
ComparisonCountedI32(x)
}
}
pub struct StandardComparisonCountedI32Distribution {}
impl Distribution<ComparisonCountedI32> for StandardComparisonCountedI32Distribution {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> ComparisonCountedI32 {
return rng.sample::<i32, rand::distributions::Standard>(rand::distributions::Standard).into()
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct ComparisonCounts {
pub partial_ord: usize,
pub ord: usize,
pub eq: usize,
pub neq: usize,
}
impl ComparisonCounts {
pub fn now() -> Self {
ComparisonCounts {
partial_ord: PARTIAL_ORD_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
ord: ORD_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
eq: PARTIAL_EQ_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
neq: PARTIAL_NEQ_COMPARISON_COUNTER.load(atomic::Ordering::SeqCst),
}
}
pub fn take_difference(&mut self) {
let mut now = ComparisonCounts::now();
assert!(now.partial_ord >= self.partial_ord);
now.partial_ord -= self.partial_ord;
assert!(now.ord >= self.ord);
now.ord -= self.ord;
assert!(now.eq >= self.eq);
now.eq -= self.eq;
assert!(now.neq >= self.neq);
now.neq -= self.neq;
mem::swap(&mut now, self);
}
}
impl Add for ComparisonCounts {
type Output = Self;
fn add(self, rhs: Self) -> Self {
ComparisonCounts {
partial_ord: self.partial_ord + rhs.partial_ord,
ord: self.ord + rhs.ord,
eq: self.eq + rhs.eq,
neq: self.neq + rhs.neq,
}
}
}
pub trait HasDistribution: Sized {
type Dist: rand::distributions::Distribution<Self>;
fn distribution() -> Self::Dist;
}
impl HasDistribution for i32 {
type Dist = Standard;
fn distribution() -> Standard { Standard }
}
impl HasDistribution for i128 {
type Dist = Standard;
fn distribution() -> Standard { Standard }
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct U32768 {
value: BigUint,
}
pub struct U32768Distribution {}
impl rand::distributions::Distribution<U32768> for U32768Distribution {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> U32768 {
let mut result = BigUint::default();
for _ in 0..256 {
result <<= 128;
result += rng.sample::<u128, Standard>(Standard).to_biguint().unwrap();
}
U32768 { value: result, }
}
}
impl HasDistribution for U32768 {
type Dist = U32768Distribution;
fn distribution() -> U32768Distribution { U32768Distribution{} }
}
/// Returns a sequence of `size` elements generated deterministically from an
/// RNG with a fixed seed.
pub fn get_values<T: HasDistribution>(size: usize) -> Vec<T> {
let seed: [u8; 32] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31];
let mut rng: StdRng = SeedableRng::from_seed(seed);
rng.sample_iter(&T::distribution()).take(size).collect()
}
// /// Runs benchmarks over sequences of size `$sizes`. For example:
// ///
// /// ```rust,noexec
// /// fn bench_something(c: &mut Criterion) {
// /// do_comparison_counted_i32_bench!(c, WeakHeap::new, 1..127);
// /// }
// /// ```
// ///
// /// Benchmarks will be run using a customized version of `i32` that counts the
// /// number of comparison operations performed.
// #[macro_export]
// macro_rules! do_comparison_counted_i32_bench {
// ($bencher: ident, $heap_factory: expr, $sizes: expr) => ({
// use $crate::benches::{ComparisonCountedI32/*, ComparisonCounts*/};
// use std::collections::HashMap;
// let mut all_values = HashMap::new();
// let mut all_sorted = HashMap::new();
// for size in $sizes {
// let values: Vec<ComparisonCountedI32> =
// $crate::benches::get_values::<i32>(size).into_iter().map(|x| x.into()).collect();
// let sorted = {
// let mut v = values.clone();
// v.sort_by(|x, y| y.cmp(x));
// v
// };
// all_values.insert(size, values);
// all_sorted.insert(size, sorted);
// }
// $bencher.bench_function_over_inputs(
// &format!("sort (counting comparisons) {}", stringify!($heap_factory)),
// move |b: &mut criterion::Bencher, size: &usize| {
// // let mut all_counts = Vec::new();
// // let mut iterations = 0;
// let values = all_values.get(size).unwrap();
// let sorted = all_sorted.get(size).unwrap();
// b.iter(|| {
// // iterations += 1;
// // let mut counts = ComparisonCounts::now();
// let mut heap = $heap_factory();
// for v in values {
// heap.push(*v);
// }
// let mut heap_sorted = Vec::with_capacity(heap.len());
// while let Some(x) = heap.pop() {
// heap_sorted.push(x);
// }
// // counts.take_difference();
// // all_counts.push(counts);
// assert_eq!(heap_sorted, *sorted);
// });
// // let total_counts = all_counts.into_iter().fold(
// // ComparisonCounts::default(), |acc, x| acc + x);
// // println!("\ndo_comparison_counted_bench({}, {}) partial_ord {:.2}, ord {:.2}, eq {:.2}, ne {:.2}",
// // stringify!($heap_factory), size,
// // (total_counts.partial_ord as f32) / ((size * iterations) as f32),
// // (total_counts.ord as f32) / ((size * iterations) as f32),
// // (total_counts.eq as f32) / ((size * iterations) as f32),
// // (total_counts.neq as f32) / ((size * iterations) as f32));
// }, $sizes);
// })
// }
/// Runs benchmarks over sequences of size `$sizes`.
#[macro_export]
macro_rules! do_bench {
($bencher: ident, $type: ty, $heap_factory: expr, $sizes: expr) => ({
use std::collections::HashMap;
let mut all_values = HashMap::new();
let mut all_sorted = HashMap::new();
for size in $sizes {
let values: Vec<$type> = $crate::benches::get_values(size);
let sorted = {
let mut v = values.clone();
v.sort_by(|x, y| y.cmp(x));
v
};
all_values.insert(size, values);
all_sorted.insert(size, sorted);
}
$bencher.bench_function_over_inputs(
&format!("sort ({}) {}", stringify!($type), stringify!($heap_factory)),
move |b: &mut criterion::Bencher, size: &usize| {
let values = all_values.get(&size).unwrap();
let sorted = all_sorted.get(size).unwrap();
b.iter(|| {
let mut heap = $heap_factory();
for v in values {
heap.push(v.clone());
}
let mut heap_sorted = Vec::with_capacity(heap.len());
while let Some(x) = heap.pop() {
heap_sorted.push(x);
}
assert_eq!(heap_sorted, *sorted);
});
}, $sizes);
})
}
pub mod tiny;
// pub mod small;
// pub mod medium;
// pub mod large;

32
src/benches/large.rs Normal file
View File

@ -0,0 +1,32 @@
/// Criterion group definitions for large tests.
use std::collections::BinaryHeap;
use crate::WeakHeap;
fn sizes() -> Range<usize> { 1024..4096 }
fn bench_i32_sort_binary(c: &mut Criterion) {
do_bench!(c, i32, BinaryHeap::new, sizes())
}
criterion_group!(i32_sort_binary, bench_i32_sort_binary);
fn bench_i32_sort_weak(c: &mut Criterion) {
do_bench!(c, i32, WeakHeap::new, sizes())
}
criterion_group!(i32_sort_weak, bench_i32_sort_weak);
fn bench_comparison_counted_i32_sort_binary(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);
fn bench_comparison_counted_i32_sort_weak(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);

32
src/benches/medium.rs Normal file
View File

@ -0,0 +1,32 @@
/// Criterion group definitions for medium tests.
use std::collections::BinaryHeap;
use crate::WeakHeap;
fn sizes() -> Range<usize> { 256..1024 }
fn bench_i32_sort_binary(c: &mut Criterion) {
do_bench!(c, i32, BinaryHeap::new, sizes())
}
criterion_group!(i32_sort_binary, bench_i32_sort_binary);
fn bench_i32_sort_weak(c: &mut Criterion) {
do_bench!(c, i32, WeakHeap::new, sizes())
}
criterion_group!(i32_sort_weak, bench_i32_sort_weak);
fn bench_comparison_counted_i32_sort_binary(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);
fn bench_comparison_counted_i32_sort_weak(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);

32
src/benches/small.rs Normal file
View File

@ -0,0 +1,32 @@
/// Criterion group definitions for small tests.
use std::collections::BinaryHeap;
use crate::WeakHeap;
fn sizes() -> Range<usize> { 128..256 }
fn bench_i32_sort_binary(c: &mut Criterion) {
do_bench!(c, i32, BinaryHeap::new, sizes())
}
criterion_group!(i32_sort_binary, bench_i32_sort_binary);
fn bench_i32_sort_weak(c: &mut Criterion) {
do_bench!(c, i32, WeakHeap::new, sizes())
}
criterion_group!(i32_sort_weak, bench_i32_sort_weak);
fn bench_comparison_counted_i32_sort_binary(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);
fn bench_comparison_counted_i32_sort_weak(c: &mut Criterion) {
do_comparison_counted_bench!(c, BinaryHeap::new, sizes())
}
criterion_group!(comparison_counted_i32_sort_weak,
bench_comparison_counted_i32_sort_weak);

59
src/benches/tiny.rs Normal file
View File

@ -0,0 +1,59 @@
/// Criterion group definitions for tiny tests.
use criterion::{Criterion, criterion_group};
use std::collections::BinaryHeap;
use std::ops::Range;
use crate::WeakHeap;
use crate::benches::U32768;
fn sizes() -> Range<usize> { 1..128 }
fn bench_i32_sort_binary(c: &mut Criterion) {
do_bench!(c, i32, BinaryHeap::new, sizes())
}
criterion_group!(i32_sort_binary, bench_i32_sort_binary);
fn bench_i32_sort_weak(c: &mut Criterion) {
do_bench!(c, i32, WeakHeap::new, sizes())
}
criterion_group!(i32_sort_weak, bench_i32_sort_weak);
fn bench_i128_sort_binary(c: &mut Criterion) {
do_bench!(c, i128, BinaryHeap::new, sizes())
}
criterion_group!(i128_sort_binary, bench_i128_sort_binary);
fn bench_i128_sort_weak(c: &mut Criterion) {
do_bench!(c, i128, WeakHeap::new, sizes())
}
criterion_group!(i128_sort_weak, bench_i128_sort_weak);
fn bench_u32768_sort_binary(c: &mut Criterion) {
do_bench!(c, U32768, BinaryHeap::new, sizes())
}
criterion_group!(u32768_sort_binary, bench_u32768_sort_binary);
fn bench_u32768_sort_weak(c: &mut Criterion) {
do_bench!(c, U32768, WeakHeap::new, sizes())
}
criterion_group!(u32768_sort_weak, bench_u32768_sort_weak);
// fn bench_comparison_counted_i32_sort_binary(c: &mut Criterion) {
// do_comparison_counted_i32_bench!(c, BinaryHeap::new, sizes())
// }
// criterion_group!(comparison_counted_i32_sort_binary,
// bench_comparison_counted_i32_sort_binary);
// fn bench_comparison_counted_i32_sort_weak(c: &mut Criterion) {
// do_comparison_counted_i32_bench!(c, BinaryHeap::new, sizes())
// }
// criterion_group!(comparison_counted_i32_sort_weak,
// bench_comparison_counted_i32_sort_weak);

View File

@ -27,6 +27,8 @@ use std::cmp::Ord;
use std::fmt;
use std::ptr;
#[cfg(feature = "benchmark-definitions")] pub mod benches;
/// An entry in the heap, consisting of a bit that indicates whether the roles
/// of its left and right children are swapped, and the actual value being
/// stored in the heap.
@ -191,10 +193,11 @@ impl<T: fmt::Debug + Ord> WeakHeap<T> {
#[cfg(test)]
mod tests {
use super::WeakHeap;
use rand::{Rng, SeedableRng, StdRng};
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
pub fn get_values(size: usize) -> Vec<i32> {
let seed: &[_] = &[1, 2, 3, 4];
let seed: [u8; 32] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31];
let mut rng: StdRng = SeedableRng::from_seed(seed);
(0..size).map(|_| rng.gen::<i32>()).map(|x| x.into()).collect()
}