rspack_allocative/lib.rs
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is dual-licensed under either the MIT license found in the
5 * LICENSE-MIT file in the root directory of this source tree or the Apache
6 * License, Version 2.0 found in the LICENSE-APACHE file in the root directory
7 * of this source tree. You may select, at your option, one of the
8 * above-listed licenses.
9 */
10
11//! # Allocative
12//!
13//! Crate implements lightweight memory profiler which allows
14//! object traversal and size introspection.
15//!
16//! An object implementing [`Allocative`] trait is introspectable, and this crate
17//! provides two utilities to work with such objects:
18//! * [`FlameGraphBuilder`] to build a flame graph of object tree
19//! * [`size_of_unique_allocated_data`] provides estimation
20//! of how much allocated memory the value holds
21//!
22//! ## Allocative overhead
23//!
24//! When allocative is used, binary size is slightly increased due to implementations
25//! of [`Allocative`] trait, but it has no runtime/memory overhead when it is not used.
26//!
27//! ## How it is different from other call-stack malloc profilers like jemalloc heap profiler
28//!
29//! Allocative is not a substitute for call stack malloc profiler,
30//! it provides a different view on memory usage.
31//!
32//! Here are some differences between allocative and call-stack malloc profiler:
33//!
34//! * Allocative requires implementation of [`Allocative`] trait for each type
35//! which needs to be measured, and some setup in the program to enable it
36//! * Allocative flamegraph shows object by object tree, not by call stack
37//! * Allocative shows gaps in allocated memory,
38//! e.g. spare capacity of collections or too large padding in structs or enums
39//! * Allocative allows profiling non-malloc allocations (for example, allocations within [bumpalo])
40//! * Allocative allows profiling of memory for subset of the process data
41//! (for example, measure the size of RPC response before serialization)
42//!
43//! [bumpalo]: https://github.com/fitzgen/bumpalo
44
45#![cfg_attr(rust_nightly, feature(const_type_name))]
46#![cfg_attr(rust_nightly, feature(never_type))]
47#![deny(rustdoc::broken_intra_doc_links)]
48#![allow(clippy::empty_enum)]
49
50mod allocative_trait;
51mod flamegraph;
52mod global_root;
53pub(crate) mod golden;
54mod impls;
55mod key;
56mod rc_str;
57mod size_of;
58mod test_derive;
59mod visitor;
60
61pub use allocative_derive::Allocative;
62pub use allocative_derive::root;
63
64pub use crate::allocative_trait::Allocative;
65pub use crate::flamegraph::FlameGraph;
66pub use crate::flamegraph::FlameGraphBuilder;
67pub use crate::global_root::register_root;
68pub use crate::key::Key;
69pub use crate::size_of::size_of_unique;
70pub use crate::size_of::size_of_unique_allocated_data;
71pub use crate::visitor::Visitor;
72
73#[doc(hidden)]
74pub mod __macro_refs {
75 pub use ctor;
76}
77
78/// Create a `const` of type `Key` with the provided `ident` as the value and
79/// return that value. This allows the keys to be placed conveniently inline
80/// without any performance hit because unlike calling `Key::new` this is
81/// guaranteed to be evaluated at compile time.
82///
83/// The main use case is manual implementations of [`Allocative`], like so:
84///
85/// ```
86/// use allocative::Allocative;
87/// use allocative::Visitor;
88/// use allocative::ident_key;
89///
90/// struct MyStruct {
91/// foo: usize,
92/// bar: Vec<()>,
93/// }
94///
95/// impl Allocative for MyStruct {
96/// fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
97/// let mut visitor = visitor.enter_self(self);
98/// visitor.visit_field(ident_key!(foo), &self.foo);
99/// visitor.visit_field(ident_key!(bar), &self.bar);
100/// visitor.exit();
101/// }
102/// }
103/// ```
104#[macro_export]
105macro_rules! ident_key {
106 ($name:ident) => {{
107 const KEY: $crate::Key = $crate::Key::new(stringify!($name));
108 KEY
109 }};
110}
111
112#[test]
113fn ident_key() {
114 assert_eq!(ident_key!(foo), Key::new("foo"));
115}