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 AllocProfiler
impl AllocProfiler
Sourcepub const fn system() -> AllocProfiler
pub const fn system() -> AllocProfiler
Profiles the System allocator.
Source§impl<A> AllocProfiler<A>
impl<A> AllocProfiler<A>
Sourcepub const fn new(alloc: A) -> AllocProfiler<A>
pub const fn new(alloc: A) -> AllocProfiler<A>
Profiles a GlobalAlloc.
Trait Implementations§
Source§impl<Alloc> Debug for AllocProfiler<Alloc>where
Alloc: Debug,
impl<Alloc> Debug for AllocProfiler<Alloc>where
Alloc: Debug,
Source§impl<Alloc> Default for AllocProfiler<Alloc>where
Alloc: Default,
impl<Alloc> Default for AllocProfiler<Alloc>where
Alloc: Default,
Source§fn default() -> AllocProfiler<Alloc>
fn default() -> AllocProfiler<Alloc>
Source§impl<A> GlobalAlloc for AllocProfiler<A>where
A: GlobalAlloc,
impl<A> GlobalAlloc for AllocProfiler<A>where
A: GlobalAlloc,
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