use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicU64, Ordering};
static ALLOCATED_BYTES: AtomicU64 = AtomicU64::new(0);
static ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);
pub struct TrackingAllocator;
unsafe impl GlobalAlloc for TrackingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let ptr = unsafe { System.alloc(layout) };
if !ptr.is_null() {
ALLOCATED_BYTES.fetch_add(layout.size() as u64, Ordering::Relaxed);
ALLOCATION_COUNT.fetch_add(1, Ordering::Relaxed);
}
ptr
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) };
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let ptr = unsafe { System.alloc_zeroed(layout) };
if !ptr.is_null() {
ALLOCATED_BYTES.fetch_add(layout.size() as u64, Ordering::Relaxed);
ALLOCATION_COUNT.fetch_add(1, Ordering::Relaxed);
}
ptr
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let new_ptr = unsafe { System.realloc(ptr, layout, new_size) };
if !new_ptr.is_null() {
if new_size > layout.size() {
ALLOCATED_BYTES.fetch_add((new_size - layout.size()) as u64, Ordering::Relaxed);
}
ALLOCATION_COUNT.fetch_add(1, Ordering::Relaxed);
}
new_ptr
}
}
pub fn current_allocation() -> (u64, u64) {
(
ALLOCATED_BYTES.load(Ordering::Relaxed),
ALLOCATION_COUNT.load(Ordering::Relaxed),
)
}
pub fn reset_allocation_counter() {
ALLOCATED_BYTES.store(0, Ordering::Relaxed);
ALLOCATION_COUNT.store(0, Ordering::Relaxed);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_reset_allocation_counter() {
ALLOCATED_BYTES.store(1000, std::sync::atomic::Ordering::Relaxed);
ALLOCATION_COUNT.store(5, std::sync::atomic::Ordering::Relaxed);
reset_allocation_counter();
let (bytes, count) = current_allocation();
assert_eq!(bytes, 0);
assert_eq!(count, 0);
}
#[test]
fn test_current_allocation_reads_atomics() {
ALLOCATED_BYTES.store(2048, std::sync::atomic::Ordering::Relaxed);
ALLOCATION_COUNT.store(10, std::sync::atomic::Ordering::Relaxed);
let (bytes, count) = current_allocation();
assert_eq!(bytes, 2048);
assert_eq!(count, 10);
reset_allocation_counter();
}
}