|
| 1 | +# MallocSizeOf |
| 2 | + |
| 3 | +A an allocator-agnostic crate for measuring the runtime size of a value |
| 4 | +including the size of any heap allocations that are owned by that value. |
| 5 | + |
| 6 | +- The core abstraction is provided by the [`MallocSizeOf`] trait which should be implemented for all |
| 7 | + types whose size you wish to measure. |
| 8 | +- A derive macro for implementing this trait on structs is provided by the [malloc_size_of_derive](https://docs.rs/malloc_size_of_derive) crate |
| 9 | +- Additionally there are [`MallocUnconditionalSizeOf`], [`MallocConditionalSizeOf`] traits for measuring |
| 10 | + types where ownership is shared (such as `Arc` and `Rc`). |
| 11 | +- Each of these traits also has a "shallow" variant ([`MallocShallowSizeOf`], [`MallocUnconditionalShallowSizeOf`], and [`MallocConditionalShallowSizeOf`]) which only measure the heap size of the value passed |
| 12 | + and not any nested allocations. |
| 13 | + |
| 14 | +All of these traits rely on being provided with an instance of [`MallocSizeOfOps`] which allows size computations |
| 15 | +to call into the allocator to ask it for the underlyinhg size of the allocations backing data structures. |
| 16 | + |
| 17 | +This crate is used by both Servo and Firefox for memory usage calculation. |
| 18 | + |
| 19 | +## Features |
| 20 | + |
| 21 | +- It isn't bound to a particular heap allocator. |
| 22 | +- It provides traits for both "shallow" and "deep" measurement, which gives |
| 23 | + flexibility in the cases where the traits can't be used. |
| 24 | +- It allows for measuring blocks even when only an interior pointer can be |
| 25 | + obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies |
| 26 | + on the heap allocator having suitable support, which `jemalloc` has.) |
| 27 | +- It allows handling of types like `Rc` and `Arc` by providing traits that |
| 28 | + are different to the ones for non-graph structures. |
| 29 | + |
| 30 | +## Suggested usage |
| 31 | + |
| 32 | +- When possible, use the `MallocSizeOf` trait. (Deriving support is |
| 33 | + provided by the `malloc_size_of_derive` crate.) |
| 34 | +- If you need an additional synchronization argument, provide a function |
| 35 | + that is like the standard trait method, but with the extra argument. |
| 36 | +- If you need multiple measurements for a type, provide a function named |
| 37 | + `add_size_of` that takes a mutable reference to a struct that contains |
| 38 | + the multiple measurement fields. |
| 39 | +- When deep measurement (via `MallocSizeOf`) cannot be implemented for a |
| 40 | + type, shallow measurement (via `MallocShallowSizeOf`) in combination with |
| 41 | + iteration can be a useful substitute. |
| 42 | +- `Rc` and `Arc` are always tricky, which is why `MallocSizeOf` is not (and |
| 43 | + should not be) implemented for them. |
| 44 | +- If an `Rc` or `Arc` is known to be a "primary" reference and can always |
| 45 | + be measured, it should be measured via the `MallocUnconditionalSizeOf` |
| 46 | + trait. |
| 47 | +- If an `Rc` or `Arc` should be measured only if it hasn't been seen |
| 48 | + before, it should be measured via the `MallocConditionalSizeOf` trait. |
| 49 | +- Using universal function call syntax is a good idea when measuring boxed |
| 50 | + fields in structs, because it makes it clear that the Box is being |
| 51 | + measured as well as the thing it points to. E.g. |
| 52 | + `<Box<_> as MallocSizeOf>::size_of(field, ops)`. |
0 commit comments