When optimizing Rust code it’s sometimes useful to know how big a type is, i.e. how many bytes it takes up in memory. std::mem::size_of
can tell you, but often you want to know the exact layout as well. For example, an enum might be surprisingly big, in which case you probably will want to know if, for example, there is one variant that is much bigger than the others.
The -Zprint-type-sizes
option does exactly this. It isn’t enabled on release versions of rustc, so you’ll need to a nightly version of rustc. Here is one possible invocation:
cargo +nightly rustc -- -Zprint-type-sizes
It will print out details of the size, layout, and alignment of all types in use. For example, for this type:
enum E { A, B(i32), C(u64, u8, u64, u8), D(Vec<u32>), }
it prints the following, plus info about a few built-in types:
print-type-size type: `E`: 32 bytes, alignment: 8 bytes print-type-size discriminant: 1 bytes print-type-size variant `A`: 0 bytes print-type-size variant `B`: 7 bytes print-type-size padding: 3 bytes print-type-size field `.0`: 4 bytes, alignment: 4 bytes print-type-size variant `C`: 23 bytes print-type-size field `.1`: 1 bytes print-type-size field `.3`: 1 bytes print-type-size padding: 5 bytes print-type-size field `.0`: 8 bytes, alignment: 8 bytes print-type-size field `.2`: 8 bytes print-type-size variant `D`: 31 bytes print-type-size padding: 7 bytes print-type-size field `.0`: 24 bytes, alignment: 8 bytes
It shows:
- the size and alignment of the type;
- for enums, the size of the discriminant;
- for enums, the size of each variant;
- the size, alignment, and ordering of all fields (note that the compiler has reordered variant
C
‘s fields to minimize the size ofE
); - the size and location of all padding.
Every detail you could possibly want is there. Brilliant!
For rustc developers, there’s an extra-special trick for getting the size of a type within rustc itself. Put code like this into a file a.rs
:
#![feature(rustc_private)] extern crate syntax; use syntax::ast::Expr; fn main() { let _x = std::mem::size_of::<Expr>(); }
and then compile it like this:
RUSTC_BOOTSTRAP=1 rustc -Zprint-type-sizes a.rs
I won’t pretend to understand how it works, but the use of rustc_private
and RUSTC_BOOTSTRAP
somehow let you see inside rustc while using it, rather than while compiling it. I have used this trick for PRs such as this one.