mem_dbg
Traits and associated procedural macros to recursively compute the memory usage of a data structure or print its layout.
The standard library function [std::mem::size_of] returns the stack size of a type in bytes, but
it does not take into consideration heap memory. This crate provides a trait [MemSize] and an associated procedural macro
for that purpose. Moreover, the trait [MemDbg] can be used to display the recursive layout of a data structure, together
with the size of each part.
Both traits accept options that can change their behavior (e.g., follow references or not) or the way the data is displayed (e.g., humanize the size or display it as a percentage of the total size).
Example
use *;
let b = Vecwith_capacity;
let s = Struct ;
println!;
println!;
s.mem_dbg.unwrap;
The previous program prints:
size: 815
capacity: 1215
815 B 100.00% ⏺: (usize, example::Struct<example::TestEnum, example::Data<alloc::vec::Vec<u8>>>)
8 B 0.98% ├╴0: usize
807 B 99.02% ╰╴1: example::Struct<example::TestEnum, example::Data<alloc::vec::Vec<u8>>>
16 B 1.96% ├╴a: example::TestEnum
│ ├╴Variant: Unnamed
8 B 0.98% │ ├╴0: usize
1 B 0.12% │ ╰╴1: u8
783 B 96.07% ├╴b: example::Data<alloc::vec::Vec<u8>>
724 B 88.83% │ ├╴a: alloc::vec::Vec<u8>
24 B 2.94% │ ├╴b: alloc::vec::Vec<i32>
35 B 4.29% │ ╰╴c: (usize, alloc::string::String)
8 B 0.98% │ ├╴0: usize
27 B 3.31% │ ╰╴1: alloc::string::String
8 B 0.98% ╰╴test: isize
If we add the flags [DbgFlags::CAPACITY] and [DbgFlags::HUMANIZE] it prints:
size: 815
capacity: 1215
1.215 kB 100.00% ⏺: (usize, example::Struct<example::TestEnum, example::Data<alloc::vec::Vec<u8>>>)
8 B 0.66% ├╴0: usize
1.207 kB 99.34% ╰╴1: example::Struct<example::TestEnum, example::Data<alloc::vec::Vec<u8>>>
16 B 1.32% ├╴a: example::TestEnum
│ ├╴Variant: Unnamed
8 B 0.66% │ ├╴0: usize
1 B 0.08% │ ╰╴1: u8
1.183 kB 97.37% ├╴b: example::Data<alloc::vec::Vec<u8>>
724 B 59.59% │ ├╴a: alloc::vec::Vec<u8>
424 B 34.90% │ ├╴b: alloc::vec::Vec<i32>
35 B 2.88% │ ╰╴c: (usize, alloc::string::String)
8 B 0.66% │ ├╴0: usize
27 B 2.22% │ ╰╴1: alloc::string::String
8 B 0.66% ╰╴test: isize
If we use [DbgFlags::empty()] it prints:
size: 815
capacity: 1215
4815 B ⏺
8 B ├╴0
4807 B ╰╴1
16 B ├╴a
│├╴Variant: Unnamed
8 B │├╴0
1 B │╰╴1
4783 B ├╴b
724 B │├╴a
4024 B │├╴b
35 B │╰╴c
8 B │ ├╴0
27 B │ ╰╴1
8 B ╰╴test
Caveats
-
We support out-of-the-box most basic types, and tuples up to size ten. The derive macros
MemSize/MemDbgwill generate implementations for structs and enums whose fields implement the associated interface: if this is not the case (e.g., because of the orphan rule) one can implement the traits manually. -
Computation of the size of arrays, slices and vectors will be performed by iterating over their elements unless the type is a copy type that does not contain references and it is declared as such using the attribute
#[copy_type]. See [CopyType] for more details. -
The content of vectors and slices is not expanded recursively as the output might be too complex; this might change in the future (e.g., via a flag) should interesting use cases arise.
-
HashMaps,HashSet,BTreeMap, andBTreeSet, are not currently supported as we still have to figure out a way to precisely measure their memory size and capacity.