diff --git a/Cargo.toml b/Cargo.toml index 3395d17..cfbafb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,11 @@ license = "MIT" [lib] name = "lifeguard" +[[bench]] +name = "lib" +harness = false + [dependencies] + +[dev-dependencies] +criterion = "0.2" diff --git a/benches/lib.rs b/benches/lib.rs index b5df750..b16f7eb 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -1,35 +1,30 @@ -#![feature(test)] -extern crate test; +#[macro_use] +extern crate criterion; extern crate lifeguard; -#[cfg(test)] -mod tests { - use test::Bencher; - use test::black_box; - use lifeguard::{Pool,Recycled,RcRecycled}; +use criterion::{black_box, Criterion}; - const ITERATIONS : u32 = 10_000; +use lifeguard::{Pool,Recycled,RcRecycled}; - // Calling String::new() is very close to a no-op; no actual allocation - // is performed until bytes are pushed onto the end of the String. As such, - // we need to explicitly ask for some space to be available to trigger allocation. - const EMPTY_STRING_CAPACITY : usize = 4; +const ITERATIONS : u32 = 10_000; - #[bench] - fn allocation_standard(b: &mut Bencher) { - b.iter(|| { - for _ in 0..ITERATIONS { - let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); - let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); - let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); - let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); - let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); - } - }); - } +// Calling String::new() is very close to a no-op; no actual allocation +// is performed until bytes are pushed onto the end of the String. As such, +// we need to explicitly ask for some space to be available to trigger allocation. +const EMPTY_STRING_CAPACITY : usize = 4; + +fn allocation(c: &mut Criterion) { + c.bench_function("allocation standard", |b| b.iter(|| { + for _ in 0..ITERATIONS { + let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); + let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); + let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); + let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); + let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY)); + } + })); - #[bench] - fn allocation_pooled(b: &mut Bencher) { + c.bench_function("allocation pooled", |b| { let pool : Pool = Pool::with_size(5); b.iter(|| { for _ in 0..ITERATIONS { @@ -40,10 +35,9 @@ mod tests { let _string = pool.new(); } }); - } + }); - #[bench] - fn allocation_pooled_rc(b: &mut Bencher) { + c.bench_function("allocation pooled rc", |b| { let pool : Pool = Pool::with_size(5); b.iter(|| { for _ in 0..ITERATIONS { @@ -54,10 +48,11 @@ mod tests { let _string = pool.new_rc(); } }); - } + }); +} - #[bench] - fn initialized_allocation_standard(b: &mut Bencher) { +fn initialized_allocation(c: &mut Criterion) { + c.bench_function("initialized allocation standard", |b| { b.iter(|| { for _ in 0..ITERATIONS { let _string = "man".to_owned(); @@ -67,10 +62,9 @@ mod tests { let _string = "cheese".to_owned(); } }); - } + }); - #[bench] - fn initialized_allocation_pooled(b: &mut Bencher) { + c.bench_function("initialized allocation pooled", |b| { let pool : Pool = Pool::with_size(5); b.iter(|| { for _ in 0..ITERATIONS { @@ -81,10 +75,9 @@ mod tests { let _string = pool.new_from("cheese"); } }); - } + }); - #[bench] - fn initialized_allocation_pooled_rc(b: &mut Bencher) { + c.bench_function("initialized allocation pooled rc", |b| { let pool : Pool = Pool::with_size(5); b.iter(|| { for _ in 0..ITERATIONS { @@ -95,10 +88,9 @@ mod tests { let _string = pool.new_rc_from("cheese"); } }); - } + }); - #[bench] - fn initialized_allocation_pooled_with_cap_empty(b: &mut Bencher) { + c.bench_function("initialized allocation pooled with cap empty", |b| { let pool : Pool = Pool::with_size_and_max(0, 5); b.iter(|| { for _ in 0..ITERATIONS { @@ -109,10 +101,9 @@ mod tests { let _string = pool.new_from("cheese"); } }); - } + }); - #[bench] - fn initialized_allocation_pooled_with_cap_full(b: &mut Bencher) { + c.bench_function("initialized allocation pooled with cap full", |b| { let pool : Pool = Pool::with_size_and_max(5, 5); b.iter(|| { for _ in 0..ITERATIONS { @@ -123,10 +114,9 @@ mod tests { let _string = pool.new_from("cheese"); } }); - } + }); - #[bench] - fn initialized_allocation_pooled_with_low_cap(b: &mut Bencher) { + c.bench_function("initialized allocation pooled with low cap", |b| { let pool : Pool = Pool::with_size_and_max(0, 2); b.iter(|| { for _ in 0..ITERATIONS { @@ -137,58 +127,62 @@ mod tests { let _string = pool.new_from("cheese"); } }); - } + }); +} - #[bench] - fn vec_vec_str_standard(bencher: &mut Bencher) { - bencher.iter(|| { - let mut v1 = Vec::new(); - for _ in 0..100 { - let mut v2 = Vec::new(); - for _ in 0..100 { - v2.push(("test!").to_owned()); - } - v1.push(v2); - } - v1 - }); - } - - #[bench] - fn vec_vec_str_pooled(bencher: &mut Bencher) { - // Note that because we're using scoped values (not Rc'ed values) - // and we're storing items from one pool in the other, - // the order that our pools are declared matters. - // Reversing them results in a compile error regarding lifetimes. - let str_pool : Pool = Pool::with_size(10000); - let vec_str_pool : Pool>> = Pool::with_size(100); - bencher.iter(|| { - let mut v1 = Vec::new(); +fn vec_vec_str(c: &mut Criterion) { + c.bench_function("vec vec str standard", |b| { + b.iter(|| { + let mut v1 = Vec::new(); + for _ in 0..100 { + let mut v2 = Vec::new(); for _ in 0..100 { - let mut v2 = vec_str_pool.new(); - for _ in 0..100 { - v2.push(str_pool.new_from("test!")); - } - v1.push(v2); + v2.push(("test!").to_owned()); } - v1 - }); - } - - #[bench] - fn vec_vec_str_pooled_rc(bencher: &mut Bencher) { - let vec_str_pool : Pool>> = Pool::with_size(100); - let str_pool : Pool = Pool::with_size(10000); - bencher.iter(|| { - let mut v1 = Vec::new(); + v1.push(v2); + } + v1 + }) + }); + + c.bench_function("vec vec str pooled", |b| { + // Note that because we're using scoped values (not Rc'ed values) + // and we're storing items from one pool in the other, + // the order that our pools are declared matters. + // Reversing them results in a compile error regarding lifetimes. + let str_pool : Pool = Pool::with_size(10000); + let vec_str_pool : Pool>> = Pool::with_size(100); + b.iter(|| { + let mut v1 = Vec::new(); + for _ in 0..100 { + let mut v2 = vec_str_pool.new(); for _ in 0..100 { - let mut v2 = vec_str_pool.new_rc(); - for _ in 0..100 { - v2.push(str_pool.new_rc_from("test!")); - } - v1.push(v2); + v2.push(str_pool.new_from("test!")); } - v1 - }); - } + v1.push(v2); + } + v1 + }); + }); + + c.bench_function("vec vec str pooled rc", |b| { + let vec_str_pool : Pool>> = Pool::with_size(100); + let str_pool : Pool = Pool::with_size(10000); + b.iter(|| { + let mut v1 = Vec::new(); + for _ in 0..100 { + let mut v2 = vec_str_pool.new_rc(); + for _ in 0..100 { + v2.push(str_pool.new_rc_from("test!")); + } + v1.push(v2); + } + v1 + }); + }); } + +criterion_group!(allocation_benches, allocation); +criterion_group!(initialized_allocation_benches, initialized_allocation); +criterion_group!(vec_vec_str_benches, vec_vec_str); +criterion_main!(allocation_benches, initialized_allocation_benches, vec_vec_str_benches);