|new 0.1.5||Mar 16, 2023|
|0.1.4||Mar 7, 2023|
|0.1.3||Feb 20, 2023|
#75 in Profiling
151 downloads per month
Nightly rustc provides the
print-type-sizes option for printing sizes of all types. It's especially useful for analyzing why futures are soo big, that can hurt performance a lot if such futures are moved.
print-type-sizes produces unordered and cluttered output. This crate parses that output, refine it and show top types by size in compact form.
- Sorts types by size.
- Deduplicates same types.
- Merges variants with similar layout.
- Shows layouts in compact form.
- Sorts fields by size (
- Hides small fields (
- Hides wrappers like
MaybeUninitand custom ones (
- Filters by type names (
- Limits output (
- Expands specific types with children, heuristically (
Firstly, install by using
cargo install top-type-sizes or clone the repository and run
cargo build --release.
Secondly, compile your project:
$ RUSTFLAGS=-Zprint-type-sizes cargo +nightly build -j 1 > type-sizes.txt
- It should be a fresh build without cache. Otherwise, part of info will be lost.
-Zprint-type-sizesrequires the nightly compiler.
-j 1is required to avoid incorrect shuffled output.
Finally, use this crate:
$ top-type-sizes < type-sizes.txt | less
$ top-type-sizes --help
top-type-sizes 0.1.5 USAGE: top-type-sizes [FLAGS] [OPTIONS] FLAGS: --help Prints help information -w, --remove-wrappers Removes wrappers like `MaybeUninit` -r, --reverse Prints top `limit` types in ascending order -s, --sort-fields Sorts fields by size and removes paddings -V, --version Prints version information OPTIONS: -e, --exclude <exclude>... Excludes types that match these patterns -p, --expand <expand>... Shows only types that match these patterns and their children, heuristically -f, --filter <filter>... Shows only types that match these patterns -h, --hide-less <hide-less> Hides fields with size less than this value [default: 0] -l, --limit <limit> Shows only this number of top types [default: 100]
For instance, let's analyze the
RUSTFLAGS=-Zprint-type-sizes cargo +nightly build --example chat -j 1 > chat.txt
Once the compiler's output is collected, you can perform multiple queries until results become representative.
Initially, find interesting entry functions:
top-type-sizes -f chat.rs < chat.txt | less
-f <pattern>hides all types that doesn't match the provided pattern. Note, that
async fnhas a path in a type name.
... 1032 [async fn body@examples/chat.rs:174:33: 243:2] align=8 ...
Ok, it's the
process function, let's check it and children types.
top-type-sizes -w -s -h 33 -p body@examples/chat.rs:174:33 < chat.txt | less
-whides wrappers, e.g.
1032 std::mem::MaybeUninit<[async fn body@examples/chat.rs:174:33: 243:2]> align=8 1032 variant MaybeUninit 1032 value
-ssorts fields by size and hides paddings.
-h <size>hides all fields with size less than the provided size.
-p <pattern>hides all types that aren't contained in
<patten>types. Note that the compiler doesn't provide types of fields, so this parameter filters types recursively by field sizes and can leave a lot of irrelevant types for small sizes (because they are more frequent). But it's very useful anyway.
1032 [async fn body@examples/chat.rs:174:33: 243:2] align=8 1031 variant Suspend2 472 __awaitee align=8 144 lines 40 stream 671 variant Suspend3, Suspend7, Suspend9 152 peer 144 lines 112 __awaitee align=8 40 stream 647 variant Suspend4, Suspend8, Suspend10 152 peer 144 lines 64 __awaitee 40 stream 623 variant Suspend5 152 peer 144 lines 40 stream 40 futures 599 variant Suspend6 152 peer 144 lines 40 stream 583 variant Suspend0 144 lines 40 stream 567 variant Suspend1 144 lines 40 stream 552 variant Unresumed, Returned, Panicked 40 stream 472 [async fn body@examples/chat.rs:155:27: 166:6] align=8 465 variant Suspend0 144 lines 144 lines 112 __awaitee 464 variant Unresumed, Returned, Panicked 144 lines align=8 ...
__awaitee means awaiting on an inner future.
Then, you can use
-e to refine output even more.