extern crate alloc;
extern crate object_alloc;
extern crate object_alloc_test;
extern crate rand;
extern crate sysconf;
extern crate test;
use SlabAllocBuilder;
use self::alloc::heap::{Alloc, Heap, Layout};
use self::object_alloc::{Exhausted, ObjectAlloc};
use self::test::{Bencher, black_box};
use self::object_alloc_test::leaky_alloc::LeakyAlloc;
use backing::alloc::AllocObjectAlloc;
use backing::BackingAlloc;
use SlabAlloc;
fn infer_allocator_type<T>(alloc: &mut ObjectAlloc<T>) {
if false {
let _: Result<*mut T, Exhausted> = unsafe { alloc.alloc() };
}
}
struct LeakyBackingAlloc;
impl BackingAlloc for LeakyBackingAlloc {
type Aligned = AllocObjectAlloc<LeakyAlloc>;
type Large = AllocObjectAlloc<LeakyAlloc>;
}
fn leaky_get_aligned(layout: Layout) -> Option<AllocObjectAlloc<LeakyAlloc>> {
if layout.align() == self::sysconf::page::pagesize() {
Some(AllocObjectAlloc::new(LeakyAlloc::new(), layout))
} else {
None
}
}
fn leaky_get_large(layout: Layout) -> AllocObjectAlloc<LeakyAlloc> {
AllocObjectAlloc::new(LeakyAlloc::new(), layout)
}
fn test_memory_corruption<T: Copy + Send + 'static>() {
use self::object_alloc_test::foreach_align;
use self::object_alloc_test::corruption::{CorruptionTesterDefault, TestBuilder};
use std::env;
let default = 100_000;
let iters = match env::var("SLAB_TEST_ITERS") {
Ok(val) => val.parse().unwrap_or(default),
Err(_) => default,
};
let f = |align| {
let new = move || {
SlabAllocBuilder::default()
.align(align)
.build_backing(leaky_get_aligned, leaky_get_large) as
SlabAlloc<_, _, LeakyBackingAlloc>
};
infer_allocator_type::<CorruptionTesterDefault<T>>(&mut new());
TestBuilder::new(new).test_iters(iters).test();
};
foreach_align::<CorruptionTesterDefault<T>, _>(f, self::sysconf::page::pagesize());
}
fn test_quickcheck_memory_corruption<T: Copy + Send + 'static>() {
use self::object_alloc_test::foreach_align;
use self::object_alloc_test::corruption::{CorruptionTesterDefault, TestBuilder};
use std::env;
let default = 100_000;
let tests = match env::var("SLAB_QUICKCHECK_TESTS") {
Ok(val) => val.parse().unwrap_or(default),
Err(_) => default,
};
let f = |align| {
let new = move || {
SlabAllocBuilder::default()
.align(align)
.build_backing(leaky_get_aligned, leaky_get_large) as
SlabAlloc<_, _, LeakyBackingAlloc>
};
infer_allocator_type::<CorruptionTesterDefault<T>>(&mut new());
TestBuilder::new(new)
.quickcheck_tests(tests)
.quickcheck();
};
foreach_align::<CorruptionTesterDefault<T>, _>(f, self::sysconf::page::pagesize());
}
macro_rules! make_test_memory_corruption {
($name:ident, $crate::types::Byte1) => ();
($name:ident, $crate::types::Byte2) => ();
($name:ident, $crate::types::Byte3) => ();
($name:ident, $crate::types::Byte4) => ();
($name:ident, $crate::types::Byte5) => ();
($name:ident, $crate::types::Byte6) => ();
($name:ident, $crate::types::Byte7) => ();
($name:ident, $crate::types::Byte8) => ();
($name:ident, $type:ty) => (
#[test]
fn $name() {
test_memory_corruption::<$type>();
}
);
}
macro_rules! make_test_quickcheck_memory_corruption {
($name:ident, $crate::types::Byte1) => ();
($name:ident, $crate::types::Byte2) => ();
($name:ident, $crate::types::Byte3) => ();
($name:ident, $crate::types::Byte4) => ();
($name:ident, $crate::types::Byte5) => ();
($name:ident, $crate::types::Byte6) => ();
($name:ident, $crate::types::Byte7) => ();
($name:ident, $crate::types::Byte8) => ();
($name:ident, $type:ty) => (
#[test]
#[ignore]
fn $name() {
test_quickcheck_memory_corruption::<$type>();
}
);
}
call_for_all_types_prefix!(make_test_memory_corruption, test_memory_corruption);
call_for_all_types_prefix!(make_test_quickcheck_memory_corruption,
quickcheck_memory_corruption);
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_no_free<T: Default>(b: &mut Bencher) {
let mut alloc = SlabAllocBuilder::default().build();
infer_allocator_type::<T>(&mut alloc);
b.iter(|| unsafe { black_box(alloc.alloc().unwrap()) });
use std::mem;
mem::forget(alloc);
}
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_no_free_no_init<T: Default>(b: &mut Bencher) {
let mut alloc = unsafe { SlabAllocBuilder::no_initialize().build() };
infer_allocator_type::<T>(&mut alloc);
b.iter(|| unsafe { black_box(alloc.alloc().unwrap()) });
use std::mem;
mem::forget(alloc);
}
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_no_free_heap<T: Default>(b: &mut Bencher) {
let layout = Layout::new::<T>();
b.iter(|| unsafe { black_box(Heap.alloc(layout.clone()).unwrap()) });
}
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_free_pairs<T: Default>(b: &mut Bencher) {
let mut alloc = SlabAllocBuilder::default().build();
infer_allocator_type::<T>(&mut alloc);
let t = unsafe { alloc.alloc().unwrap() };
b.iter(|| unsafe {
let t = alloc.alloc().unwrap();
black_box(t);
alloc.dealloc(t);
});
unsafe {
alloc.dealloc(t);
}
}
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_free_pairs_no_init<T: Default>(b: &mut Bencher) {
let mut alloc = unsafe { SlabAllocBuilder::no_initialize().build() };
infer_allocator_type::<T>(&mut alloc);
let t = unsafe { alloc.alloc().unwrap() };
b.iter(|| unsafe {
let t = alloc.alloc().unwrap();
black_box(t);
alloc.dealloc(t);
});
unsafe {
alloc.dealloc(t);
}
}
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
fn bench_alloc_free_pairs_heap<T: Default>(b: &mut Bencher) {
let layout = Layout::new::<T>();
b.iter(|| unsafe {
let t = Heap.alloc(layout.clone()).unwrap();
black_box(t);
Heap.dealloc(t, layout.clone());
});
}
macro_rules! make_bench_alloc_no_free {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_no_free::<$typ>(b); }
);
}
macro_rules! make_bench_alloc_no_free_no_init {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_no_free_no_init::<$typ>(b); }
);
}
macro_rules! make_bench_alloc_no_free_heap {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_no_free_heap::<$typ>(b); }
);
}
macro_rules! make_bench_alloc_free_pairs {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_free_pairs::<$typ>(b); }
);
}
macro_rules! make_bench_alloc_free_pairs_no_init {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_free_pairs_no_init::<$typ>(b); }
);
}
macro_rules! make_bench_alloc_free_pairs_heap {
($name:ident, $typ:ty) => (
#[bench]
#[cfg(feature = "build-ignored-tests")]
#[cfg_attr(not(feature = "build-ignored-tests"), allow(unused))]
#[ignore]
fn $name(b: &mut Bencher) { bench_alloc_free_pairs_heap::<$typ>(b); }
);
}
call_for_all_types_prefix!(make_bench_alloc_no_free, bench_alloc_no_free);
call_for_all_types_prefix!(make_bench_alloc_no_free_no_init,
bench_alloc_no_free_no_init);
call_for_all_types_prefix!(make_bench_alloc_no_free_heap, bench_alloc_no_free_heap);
call_for_all_types_prefix!(make_bench_alloc_free_pairs, bench_alloc_free_pairs);
call_for_all_types_prefix!(make_bench_alloc_free_pairs_no_init,
bench_alloc_free_pairs_no_init);
call_for_all_types_prefix!(make_bench_alloc_free_pairs_heap,
bench_alloc_free_pairs_heap);