pub struct Statistics<I> { /* private fields */ }Expand description
Wrapper that records allocation activity in AllocStats.
Send + Sync if I: Send + Sync. Atomic counters are themselves Sync.
§Accounting invariant
Statistics records bytes by the layout the outer caller passed in.
Wrappers below Statistics that pass the layout through unchanged
(PoisonOnFree, Quarantine, Watermark) preserve this — the bytes
counted equal the bytes the caller requested. Wrappers below
Statistics that inflate the inner layout (Canary, CacheJitter,
HugePageAligned, SplitMetadata) consume more inner-allocator bytes
than the counter reports; the counter therefore reflects “bytes the
user asked for”, not “bytes the underlying region holds”. If you need
the latter, wrap Statistics INSIDE the layout-inflating wrapper:
Canary<Statistics<Slab<T>>> counts what Slab actually carved. The
recommended position for Statistics (Statistics<PoisonOnFree<Slab>>)
treats “bytes the user asked for” as the right number to
surface to operators; flip the nesting only if you specifically need
physical accounting.
§API-misuse compile-failures (pinned)
Statistics<I> inherits the Sync property of its inner allocator.
Wrapping a !Sync allocator (such as Slab, whose UnsafeCell free
list head makes it !Sync by design) does not silently upgrade
it to Sync. Calling stats() on a shared reference across threads
when the inner is !Sync is therefore rejected at compile time:
// FAILS TO COMPILE: `Slab` is `!Sync` (UnsafeCell on the freelist
// head), so `Statistics<Slab<...>>` is also `!Sync`, and
// `assert_sync` rejects it.
use forge_alloc::InlineBacked;
use forge_alloc::Statistics;
use forge_alloc::Slab;
fn assert_sync<T: Sync>() {}
assert_sync::<Statistics<Slab<u64, InlineBacked<512>>>>();Implementations§
Trait Implementations§
Source§impl<I: Allocator> Allocator for Statistics<I>
impl<I: Allocator> Allocator for Statistics<I>
Source§fn allocate(&self, layout: NonZeroLayout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: NonZeroLayout) -> Result<NonNull<[u8]>, AllocError>
layout. The returned slice’s length is
at least layout.size() but may be larger.Source§unsafe fn usable_size(
&self,
ptr: NonNull<u8>,
layout: NonZeroLayout,
) -> Option<usize>
unsafe fn usable_size( &self, ptr: NonNull<u8>, layout: NonZeroLayout, ) -> Option<usize>
None — implementors that track usable size
override. Read moreSource§fn capacity_bytes(&self) -> Option<usize>
fn capacity_bytes(&self) -> Option<usize>
None for unbounded
allocators like System. Used by Watermark to compute thresholds.