Expand description
Lightweight heap telemetry for Rust, built on relaxed atomics.
heapster is a lightweight, generic wrapper over any GlobalAlloc
that tracks allocations, deallocations, and reallocations using pure relaxed atomics.
it is designed to be always-on, allowing you to identify allocation patterns,
diff heap usage between code paths, and export raw allocator metrics to your telemetry
dashboards with minimal overhead.
§why heapster?
Heap profilers like dhat or heaptrack capture rich per-allocation data but add significant overhead and require dedicated viewers. Heapster occupies a lighter tier: aggregate counters and histograms only, with overhead low enough to leave on in production.
- atomics-only: no mutexes, no thread-locals, no external viewer files. just relaxed atomic counters.
no_stdby default: uses onlycoreandallocin the default build; the sole default dependency isportable-atomic, which compiles down tocoreatomics on targets with native 64-bit atomics and provides a fallback elsewhere. Thefmtandserdefeatures addstdrequirements.- generic over any allocator: wraps
System, jemalloc, mimalloc, or any customGlobalAlloc. - size histograms: power-of-two buckets for allocations and reallocations make the size distribution visible at a glance.
- realloc classification: tracks growth and shrinkage of reallocations, and (orthogonally) whether they forced a full memory copy — a moved growth realloc counts towards both metrics.
- snapshot diffing:
measure()returns aStatsdelta for a closure, suitable for assertion-style tests and benchmark comparisons. - dual view of byte movement: separate “fresh-only” and “inclusive” sums let you reason about allocation pattern shape independently from total heap pressure.
§quickstart
wrap your global allocator of choice (e.g., System) in your main.rs or lib.rs:
use heapster::Heapster;
use std::alloc::System;
#[global_allocator]
static GLOBAL: Heapster<System> = Heapster::new(System);
fn main() {
// ... do some heavy work ...
// see what has transpired in the heap
let stats = GLOBAL.stats();
println!("allocated: {} bytes", stats.alloc_sum);
}§measuring specific operations
heapster lets you diff the heap stats of critical sections of code using snapshot math:
let (result, heap_diff) = GLOBAL.measure(|| {
// ... operation to measure ...
42
});
assert!(heap_diff.alloc_count < 10, "regression: the operation allocated too many times!");