📊 heapster
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, with no third-party dependencies. 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: Distinguishes between reallocations that grew in-place, shrank in-place, or forced a full memory move (copying).
- Snapshot diffing:
measure()returns aStatsdelta for a closure, suitable for assertion-style tests and benchmark comparisons.
Quickstart
Add heapster to your Cargo.toml. Enable the fmt feature if you want pretty, human-readable terminal histograms:
[]
= { = "0.5", = ["fmt"] }
Wrap your global allocator of choice (e.g., System) in your main.rs or lib.rs:
use Heapster;
use System;
static GLOBAL: = new;
Features
Cargo features are opt-in; the default build has no non-std dependencies.
fmt—Displayimpls forStatsandHistogram, including ASCII-rendered histograms. Pulls inhumansizeandnum-format.serde—Serialize/Deserializeimpls forStatsandHistogram, for exporting snapshots to JSON, MessagePack, or other formats consumed by metrics pipelines.
[]
= { = "0.5", = ["fmt", "serde"] }
Use Cases
1. Benchmarking and regression tests
Stop guessing if a PR increased allocations. heapster lets you measure the heap stats of critical sections of code.
let = GLOBAL.measure;
assert!;
2. Catching reallocation thrashing
When a Vec or String grows beyond its capacity, the underlying buffer may be moved to a new location, copying the contents. Heapster's realloc_move_count makes these moves visible so you can pre-size collections that thrash.
3. Always-On production metrics
Overhead is a small constant per allocation (typically tens of nanoseconds for the atomic operations), so Heapster can be left on in production. stats() exposes a Stats struct that's straightforward to wire into a Prometheus or other metrics endpoint, especially with the serde feature enabled.
Simple Histogram Output
The fmt feature provides Display impls that render stats and ASCII histograms.
alloc_count: 10,949,628
alloc_avg: 2.45 KiB
dealloc_count: 10,949,372
dealloc_avg: 4.09 KiB
realloc_growth_count: 365,968
realloc_growth_avg: 49.12 KiB
realloc_move_count: 351,933
realloc_move_avg: 7.21 KiB
use_curr: 260.39 KiB
use_max: 25.01 MiB
alloc_histogram:
[ 4 B .. 8 B): 2 █
[ 8 B .. 16 B): 642,064 ███████████
[ 16 B .. 32 B): 155 █
[ 32 B .. 64 B): 1,639,279 █████████████████████████████
[ 64 B .. 128 B): 1,926,643 ██████████████████████████████████
[ 128 B .. 256 B): 1,123,746 ████████████████████
[ 256 B .. 512 B): 1,284,154 ██████████████████████
[ 512 B .. 1 KiB): 2,246,658 ████████████████████████████████████████
[ 1 KiB .. 2 KiB): 1,283,935 ██████████████████████
[ 2 KiB .. 4 KiB): 160,612 ██
[ 4 KiB .. 8 KiB): 411 █
[ 8 KiB .. 16 KiB): 320,985 █████
[ 16 KiB .. 32 KiB): 1 █
[ 32 KiB .. 64 KiB): 1 █
[ 64 KiB .. 128 KiB): 320,982 █████
realloc_growth_histogram:
[ 1 B .. 2 B): 16 █
[ 2 B .. 4 B): 0
[ 4 B .. 8 B): 0
[ 8 B .. 16 B): 0
[ 16 B .. 32 B): 0
[ 32 B .. 64 B): 25,477 ███
[ 64 B .. 128 B): 14,976 █
[ 128 B .. 256 B): 4,411 █
[ 256 B .. 512 B): 106 █
[ 512 B .. 1 KiB): 0
[ 1 KiB .. 2 KiB): 0
[ 2 KiB .. 4 KiB): 0
[ 4 KiB .. 8 KiB): 0
[ 8 KiB .. 16 KiB): 0
[ 16 KiB .. 32 KiB): 0
[ 32 KiB .. 64 KiB): 320,982 ████████████████████████████████████████
License
Dual-licensed under either of:
- Creative Commons Zero v1.0 Universal (LICENSE-CC0)
- MIT License (LICENSE-MIT)
at your option.