alloc_tracker/
lib.rs

1//! Memory allocation tracking utilities for benchmarks and performance analysis.
2//!
3//! This package provides utilities to track memory allocations during code execution,
4//! enabling analysis of allocation patterns in benchmarks and performance tests.
5//!
6//! The core functionality includes:
7//! - [`Allocator`] - A Rust memory allocator wrapper that enables allocation tracking
8//! - [`Session`] - Configures allocation tracking and provides access to tracking data
9//! - [`Report`] - Thread-safe memory allocation statistics that can be merged and processed independently
10//! - [`ProcessSpan`] - Tracks process-wide memory allocation changes over a time period
11//! - [`ThreadSpan`] - Tracks thread-local memory allocation changes over a time period
12//! - [`Operation`] - Calculates mean memory allocation per operation
13//! - [`SpanBuilder`] - Builder for creating allocation tracking spans with explicit iteration counts
14//!
15//! This package is not meant for use in production, serving only as a development tool.
16//!  
17//! # Simple Usage
18//!
19//! You can track allocations like this:
20//!
21//! ```
22//! use alloc_tracker::{Allocator, Session};
23//!
24//! #[global_allocator]
25//! static ALLOCATOR: Allocator<std::alloc::System> = Allocator::system();
26//!
27//! fn main() {
28//!     let session = Session::new();
29//!
30//!     // Track a single operation
31//!     {
32//!         let operation = session.operation("my_operation");
33//!         let _span = operation.iterations(1).measure_process();
34//!         let _data = vec![1, 2, 3, 4, 5]; // This allocates memory
35//!     }
36//!
37//!     // Print results
38//!     session.print_to_stdout();
39//!
40//!     // Session automatically cleans up when dropped
41//! }
42//! ```
43//!
44//! # Tracking Mean Allocations
45//!
46//! For benchmarking scenarios, where you run multiple iterations of an operation, use [`Operation`]:
47//!
48//! ```
49//! use alloc_tracker::{Allocator, Operation, Session};
50//!
51//! #[global_allocator]
52//! static ALLOCATOR: Allocator<std::alloc::System> = Allocator::system();
53//!
54//! fn main() {
55//!     let session = Session::new();
56//!
57//!     // Track mean over multiple operations (batched for efficiency)
58//!     {
59//!         let mut string_op = session.operation("string_allocations");
60//!         let _span = string_op.iterations(10).measure_process();
61//!         for i in 0..10 {
62//!             let _data = format!("String number {}", i); // This allocates memory
63//!         }
64//!     }
65//!
66//!     // Output statistics of all operations to console
67//!     session.print_to_stdout();
68//! }
69//! ```
70//!
71//! # Overhead
72//!
73//! In single-threaded scenarios, capturing a single measurement by calling
74//! `Operation::iterations(1).measure_xyz()` incurs an overhead of approximately 2 nanoseconds
75//! on an arbitrary sample machine.
76//!
77//! Memory allocator activity is likewise slightly impacted by the tracking logic, especially
78//! in multi-threaded scenarios where additional synchronization may be introduced.
79//!
80//! # Session management
81//!
82//! Multiple [`Session`] instances can be used concurrently as they track memory allocation
83//! independently. Each session maintains its own set of operations and statistics.
84//!
85//! While [`Session`] itself is single-threaded, reports from sessions can be converted to
86//! thread-safe [`Report`] instances and sent to other threads for processing:
87//!
88//! ```
89//! use std::thread;
90//!
91//! use alloc_tracker::{Allocator, Report, Session};
92//!
93//! #[global_allocator]
94//! static ALLOCATOR: Allocator<std::alloc::System> = Allocator::system();
95//!
96//! # fn main() {
97//! let session = Session::new();
98//! {
99//!     let operation = session.operation("work");
100//!     let _span = operation.iterations(1).measure_process();
101//!     let _data = vec![1, 2, 3]; // Some allocation work
102//! }
103//!
104//! let report = session.to_report();
105//!
106//! // Report can be sent to another thread
107//! thread::spawn(move || {
108//!     report.print_to_stdout();
109//! })
110//! .join()
111//! .unwrap();
112//! # }
113//! ```
114//!
115//! # Miri compatibility
116//!
117//! Miri replaces the global allocator with its own logic, so you cannot execute code that uses
118//! this package under Miri.
119
120mod allocator;
121mod constants;
122mod operation;
123mod process_span;
124mod report;
125mod session;
126mod span_builder;
127mod thread_span;
128
129pub use allocator::*;
130pub use operation::*;
131pub use process_span::ProcessSpan;
132pub use report::{Report, ReportOperation};
133pub use session::*;
134pub use span_builder::SpanBuilder;
135pub use thread_span::ThreadSpan;