Struct divan::AllocProfiler
source · pub struct AllocProfiler<Alloc = System> { /* private fields */ }Expand description
Measures GlobalAlloc memory usage.
§Examples
The default usage is to create a
#[global_allocator] that wraps the System
allocator with AllocProfiler::system():
use std::collections::*;
use divan::AllocProfiler;
#[global_allocator]
static ALLOC: AllocProfiler = AllocProfiler::system();
fn main() {
divan::main();
}
#[divan::bench(types = [
Vec<i32>,
LinkedList<i32>,
HashSet<i32>,
])]
fn from_iter<T>() -> T
where
T: FromIterator<i32>,
{
(0..100).collect()
}
#[divan::bench(types = [
Vec<i32>,
LinkedList<i32>,
HashSet<i32>,
])]
fn drop<T>(bencher: divan::Bencher)
where
T: FromIterator<i32>,
{
bencher
.with_inputs(|| (0..100).collect::<T>())
.bench_values(std::mem::drop);
}Wrap other GlobalAlloc implementations like
mimalloc with AllocProfiler::new():
use divan::AllocProfiler;
use mimalloc::MiMalloc;
#[global_allocator]
static ALLOC: AllocProfiler<MiMalloc> = AllocProfiler::new(MiMalloc);See string
and collections
benchmarks for more examples.
§Implementation
Collecting allocation information happens at any point during which Divan is also measuring the time. As a result, counting allocations affects timing.
To reduce Divan’s footprint during benchmarking:
- Allocation information is recorded in thread-local storage to prevent
contention when benchmarks involve multiple threads, either through
options like
threadsor internally spawning their own threads. - It does not check for overflow and assumes it will not happen. This is subject to change in the future.
- Fast thread-local storage access is assembly-optimized on macOS.
Allocation information is the only data Divan records outside of timing, and thus it also has the only code that affects timing. Steps for recording alloc info:
-
Load the thread-local slot for allocation information.
On macOS, this is via the
gs/tpidrro_el0registers forpthread_getspecific. Although this is not guaranteed as stable ABI, in practice many programs assume these registers store thread-local data.thread_local!is used on all other platforms. -
Increment allocation operation invocation count and bytes count (a.k.a. size).
Allocation information is recorded in thread-local storage to prevent
slowdowns from synchronized sharing when using multiple threads, through
options like threads.
Note that allocations in threads not controlled by Divan are not currently counted.
Implementations§
source§impl<A> AllocProfiler<A>
impl<A> AllocProfiler<A>
sourcepub const fn new(alloc: A) -> Self
pub const fn new(alloc: A) -> Self
Profiles a GlobalAlloc.
Trait Implementations§
source§impl<Alloc: Debug> Debug for AllocProfiler<Alloc>
impl<Alloc: Debug> Debug for AllocProfiler<Alloc>
source§impl<Alloc: Default> Default for AllocProfiler<Alloc>
impl<Alloc: Default> Default for AllocProfiler<Alloc>
source§fn default() -> AllocProfiler<Alloc>
fn default() -> AllocProfiler<Alloc>
source§impl<A: GlobalAlloc> GlobalAlloc for AllocProfiler<A>
impl<A: GlobalAlloc> GlobalAlloc for AllocProfiler<A>
source§unsafe fn alloc(&self, layout: Layout) -> *mut u8
unsafe fn alloc(&self, layout: Layout) -> *mut u8
layout. Read moresource§unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8
alloc, but also ensures that the contents
are set to zero before being returned. Read more