re_memory/
lib.rs

1//! Run-time memory tracking and profiling.
2//!
3//! ## First steps
4//!
5//! Add `re_memory` to your `Cargo.toml`:
6//!
7//! ```toml
8//! cargo add re_memory
9//! ```
10//!
11//! Install the [`AccountingAllocator`] in your `main.rs`:
12//! ```no_run
13//! use re_memory::AccountingAllocator;
14//!
15//! #[global_allocator]
16//! static GLOBAL: AccountingAllocator<std::alloc::System>
17//!     = AccountingAllocator::new(std::alloc::System);
18//! ```
19//!
20//! ### Checking memory use
21//! Use [`MemoryUse::capture`] to get the current memory use of your application.
22//!
23//! ### Finding memory leaks
24//! Turn on memory tracking at the top of your `main()` function:
25//!
26//! ```rs
27//! re_memory::accounting_allocator::set_tracking_callstacks(true);
28//! ```
29//!
30//! Now let your app run for a while, and then call [`accounting_allocator::tracking_stats`]
31//! to get the statistics. Any memory leak should show up in
32//! [`TrackingStatistics::top_callstacks`].
33//!
34//! ### More
35//! See also [`accounting_allocator`].
36
37pub mod accounting_allocator;
38mod allocation_tracker;
39mod memory_limit;
40mod memory_use;
41mod ram_warner;
42pub mod util;
43
44#[cfg(not(target_arch = "wasm32"))]
45mod peak_memory_stats;
46
47#[cfg(not(target_arch = "wasm32"))]
48mod backtrace_native;
49
50#[cfg(not(target_arch = "wasm32"))]
51use backtrace_native::Backtrace;
52
53#[cfg(target_arch = "wasm32")]
54mod backtrace_web;
55
56#[cfg(target_arch = "wasm32")]
57use backtrace_web::Backtrace;
58
59pub use self::accounting_allocator::{AccountingAllocator, TrackingStatistics};
60pub use self::allocation_tracker::{CallstackStatistics, ReadableBacktrace};
61pub use self::memory_limit::MemoryLimit;
62pub use self::memory_use::MemoryUse;
63#[cfg(not(target_arch = "wasm32"))]
64pub use self::peak_memory_stats::PeakMemoryStats;
65pub use self::ram_warner::*;
66
67/// Number of allocation and their total size.
68#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
69pub struct CountAndSize {
70    /// Number of allocations.
71    pub count: usize,
72
73    /// Number of bytes.
74    pub size: usize,
75}
76
77impl std::fmt::Debug for CountAndSize {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        let Self { count, size } = self;
80        f.debug_struct("CountAndSize")
81            .field("count", &re_format::format_uint(*count))
82            .field("size", &re_format::format_bytes(*size as _))
83            .finish()
84    }
85}
86
87impl CountAndSize {
88    pub const ZERO: Self = Self { count: 0, size: 0 };
89
90    /// Add an allocation.
91    #[inline]
92    pub fn add(&mut self, size: usize) {
93        self.count += 1;
94        self.size += size;
95    }
96
97    /// Remove an allocation.
98    #[inline]
99    pub fn sub(&mut self, size: usize) {
100        self.count -= 1;
101        self.size -= size;
102    }
103}
104
105#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
106struct BacktraceHash(u64);
107
108impl BacktraceHash {
109    #[inline]
110    pub fn new(backtrace: &Backtrace) -> Self {
111        Self(ahash::RandomState::with_seeds(1, 2, 3, 4).hash_one(backtrace))
112    }
113}
114
115impl nohash_hasher::IsEnabled for BacktraceHash {}