Skip to main content

CountingAllocator

Struct CountingAllocator 

Source
pub struct CountingAllocator<A: Allocator> { /* private fields */ }
Expand description

An Allocator wrapper that records allocation and deallocation statistics.

Wrap any existing allocator with CountingAllocator::new(inner) to transparently instrument it. Statistics can be queried at any time via stats and reset via reset_stats.

§Thread Safety

CountingAllocator uses Cell internally, which is not Sync. It is suitable for single-threaded use only. For multi-threaded scenarios, wrap an atomic-based allocator instead.

Implementations§

Source§

impl<A: Allocator> CountingAllocator<A>

Source

pub fn new(inner: A) -> Self

Creates a new CountingAllocator wrapping inner.

All counters start at zero.

Examples found in repository?
examples/full.rs (line 10)
9fn main() {
10    let sys = CountingAllocator::new(SystemAllocator);
11    
12    println!("=== ExBox & SystemAllocator ===");
13    {
14        let b = ExBox::new(42, &sys).expect("Failed to alloc Box");
15        println!("Box value: {}", *b);
16    }
17    
18    let stats = sys.stats();
19    println!("Allocated: {} bytes", stats.bytes_allocated);
20    println!("Deallocated: {} bytes", stats.bytes_freed);
21    println!("Live bytes: {}\n", stats.bytes_live);
22
23    println!("=== ExVec & Arena (Linear Allocation) ===");
24    {
25        let arena = ArenaAllocator::new(&sys);
26        
27        let mut v = ExVec::new(&arena);
28        for i in 0..5 {
29            v.push(i * 10);
30        }
31        println!("Vec: {:?}", v.as_slice());
32        
33        arena.reset();
34        println!("Arena reset performed");
35    }
36
37    println!("\n=== ExString & Pool (Fixed Size Blocks) ===");
38    {
39        let pool = PoolAllocator::typed::<[u8; 64]>(&sys, 10)
40            .expect("Failed to create Pool");
41        
42        let mut s = ExString::new(&pool);
43        s.push_str("Hello from ZigZag!");
44        
45        println!("String in Pool: {}", s.as_str());
46        println!("Pool free slots: {}", pool.free_count());
47    }
48
49    println!("\n=== Final Global Stats ===");
50    let final_stats = sys.stats();
51    println!("Total count of alloc() calls: {}", final_stats.allocs);
52    println!("Total count of dealloc() calls: {}", final_stats.deallocs);
53    println!("Total bytes allocated: {}", final_stats.bytes_allocated);
54    println!("Total bytes freed: {}", final_stats.bytes_freed);
55    println!("Current leak/live size: {} bytes", final_stats.bytes_live);
56}
Source

pub fn stats(&self) -> AllocStats

Returns a snapshot of all statistics.

Counters are cumulative since the last call to reset_stats.

§Example
let counting = CountingAllocator::new(SystemAllocator);
let _ = unsafe { counting.alloc(Layout::new::<u64>()) };
let stats = counting.stats();
assert_eq!(stats.allocs, 1);
assert_eq!(stats.bytes_allocated, 8);
Examples found in repository?
examples/full.rs (line 18)
9fn main() {
10    let sys = CountingAllocator::new(SystemAllocator);
11    
12    println!("=== ExBox & SystemAllocator ===");
13    {
14        let b = ExBox::new(42, &sys).expect("Failed to alloc Box");
15        println!("Box value: {}", *b);
16    }
17    
18    let stats = sys.stats();
19    println!("Allocated: {} bytes", stats.bytes_allocated);
20    println!("Deallocated: {} bytes", stats.bytes_freed);
21    println!("Live bytes: {}\n", stats.bytes_live);
22
23    println!("=== ExVec & Arena (Linear Allocation) ===");
24    {
25        let arena = ArenaAllocator::new(&sys);
26        
27        let mut v = ExVec::new(&arena);
28        for i in 0..5 {
29            v.push(i * 10);
30        }
31        println!("Vec: {:?}", v.as_slice());
32        
33        arena.reset();
34        println!("Arena reset performed");
35    }
36
37    println!("\n=== ExString & Pool (Fixed Size Blocks) ===");
38    {
39        let pool = PoolAllocator::typed::<[u8; 64]>(&sys, 10)
40            .expect("Failed to create Pool");
41        
42        let mut s = ExString::new(&pool);
43        s.push_str("Hello from ZigZag!");
44        
45        println!("String in Pool: {}", s.as_str());
46        println!("Pool free slots: {}", pool.free_count());
47    }
48
49    println!("\n=== Final Global Stats ===");
50    let final_stats = sys.stats();
51    println!("Total count of alloc() calls: {}", final_stats.allocs);
52    println!("Total count of dealloc() calls: {}", final_stats.deallocs);
53    println!("Total bytes allocated: {}", final_stats.bytes_allocated);
54    println!("Total bytes freed: {}", final_stats.bytes_freed);
55    println!("Current leak/live size: {} bytes", final_stats.bytes_live);
56}
Source

pub fn reset_stats(&self)

Resets all counters to zero.

Does not affect the underlying allocator or any live allocations.

Trait Implementations§

Source§

impl<A: Allocator> Allocator for CountingAllocator<A>

Source§

unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>>

Forwards the allocation to the inner allocator and records statistics.

Only successful allocations are counted; if the inner allocator returns None, the counters are not updated.

§Safety

Inherits all safety requirements from A::alloc.

Source§

unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout)

Forwards the deallocation to the inner allocator and records statistics.

§Safety

Inherits all safety requirements from A::dealloc. In particular, ptr must have been obtained from this allocator (and therefore from its inner allocator).

Auto Trait Implementations§

§

impl<A> !Freeze for CountingAllocator<A>

§

impl<A> !RefUnwindSafe for CountingAllocator<A>

§

impl<A> Send for CountingAllocator<A>
where A: Send,

§

impl<A> !Sync for CountingAllocator<A>

§

impl<A> Unpin for CountingAllocator<A>
where A: Unpin,

§

impl<A> UnsafeUnpin for CountingAllocator<A>
where A: UnsafeUnpin,

§

impl<A> UnwindSafe for CountingAllocator<A>
where A: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.