#![allow(
missing_docs,
reason = "No need for API documentation in benchmark code"
)]
use std::alloc::{GlobalAlloc, Layout, handle_alloc_error};
use std::hint::black_box;
use alloc_tracker::{Allocator, Session};
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
#[global_allocator]
static ALLOCATOR: Allocator<std::alloc::System> = Allocator::system();
const SMALL_SIZE: usize = 64;
const LARGE_SIZE: usize = 64 * 1024;
const REALLOC_GROWN_SIZE: usize = SMALL_SIZE * 2;
criterion_group!(benches, span_overhead, allocator_overhead);
criterion_main!(benches);
fn span_overhead(c: &mut Criterion) {
let mut group = c.benchmark_group("alloc_tracker_tracking_overhead/overhead");
group.bench_function("baseline_empty", |b| {
b.iter(|| {
black_box(());
});
});
{
let alloc_session = Session::new().no_stdout().no_file();
let process_op =
alloc_session.operation("alloc_tracker_tracking_overhead/overhead/process_span_empty");
group.bench_function("process_span_empty", |b| {
b.iter(|| {
let _span = process_op.measure_process().iterations(1);
black_box(());
});
});
let thread_op =
alloc_session.operation("alloc_tracker_tracking_overhead/overhead/thread_span_empty");
group.bench_function("thread_span_empty", |b| {
b.iter(|| {
let _span = thread_op.measure_thread().iterations(1);
black_box(());
});
});
}
group.finish();
}
fn allocator_overhead(c: &mut Criterion) {
let mut group = c.benchmark_group("alloc_tracker_tracking_overhead/allocator");
let small = layout(SMALL_SIZE);
let large = layout(LARGE_SIZE);
let grown = layout(REALLOC_GROWN_SIZE);
alloc_dealloc(&ALLOCATOR, small);
group.bench_function("untracked_alloc_dealloc_small", |b| {
b.iter(|| alloc_dealloc(&std::alloc::System, black_box(small)));
});
group.bench_function("tracked_alloc_dealloc_small", |b| {
b.iter(|| alloc_dealloc(&ALLOCATOR, black_box(small)));
});
group.bench_function("untracked_alloc_dealloc_large", |b| {
b.iter(|| alloc_dealloc(&std::alloc::System, black_box(large)));
});
group.bench_function("tracked_alloc_dealloc_large", |b| {
b.iter(|| alloc_dealloc(&ALLOCATOR, black_box(large)));
});
group.bench_function("untracked_dealloc_small", |b| {
b.iter_batched(
|| allocate(&std::alloc::System, small),
|block| dealloc(&std::alloc::System, block),
BatchSize::SmallInput,
);
});
group.bench_function("tracked_dealloc_small", |b| {
b.iter_batched(
|| allocate(&ALLOCATOR, small),
|block| dealloc(&ALLOCATOR, block),
BatchSize::SmallInput,
);
});
group.bench_function("untracked_realloc_grow", |b| {
b.iter_batched(
|| allocate(&std::alloc::System, small),
|block| realloc_grow(&std::alloc::System, block, grown),
BatchSize::SmallInput,
);
});
group.bench_function("tracked_realloc_grow", |b| {
b.iter_batched(
|| allocate(&ALLOCATOR, small),
|block| realloc_grow(&ALLOCATOR, block, grown),
BatchSize::SmallInput,
);
});
group.finish();
}
fn layout(size: usize) -> Layout {
Layout::from_size_align(size, align_of::<u64>()).expect(
"a type's alignment is a non-zero power of two and the benchmark sizes are orders of \
magnitude below the layout size limit",
)
}
fn allocate<A: GlobalAlloc>(allocator: &A, layout: Layout) -> (*mut u8, Layout) {
let ptr = unsafe { allocator.alloc(layout) };
if ptr.is_null() {
handle_alloc_error(layout);
}
(ptr, layout)
}
fn alloc_dealloc<A: GlobalAlloc>(allocator: &A, layout: Layout) {
let block = allocate(allocator, layout);
black_box(block.0);
dealloc(allocator, block);
}
fn dealloc<A: GlobalAlloc>(allocator: &A, block: (*mut u8, Layout)) {
let (ptr, layout) = block;
unsafe {
allocator.dealloc(ptr, layout);
}
}
struct Block<'a, A: GlobalAlloc> {
allocator: &'a A,
ptr: *mut u8,
layout: Layout,
}
impl<A: GlobalAlloc> Drop for Block<'_, A> {
fn drop(&mut self) {
unsafe {
self.allocator.dealloc(self.ptr, self.layout);
}
}
}
fn realloc_grow<A: GlobalAlloc>(
allocator: &A,
block: (*mut u8, Layout),
grown_layout: Layout,
) -> Block<'_, A> {
let (ptr, layout) = block;
let grown = unsafe { allocator.realloc(ptr, layout, grown_layout.size()) };
if grown.is_null() {
handle_alloc_error(grown_layout);
}
Block {
allocator,
ptr: grown,
layout: grown_layout,
}
}