{"id":3197,"date":"2018-11-09T14:42:40","date_gmt":"2018-11-09T03:42:40","guid":{"rendered":"http:\/\/blog.mozilla.org\/nnethercote\/?p=3197"},"modified":"2020-05-14T10:33:41","modified_gmt":"2020-05-13T23:33:41","slug":"how-to-get-the-size-of-rust-types-with-zprint-type-sizes","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/nnethercote\/2018\/11\/09\/how-to-get-the-size-of-rust-types-with-zprint-type-sizes\/","title":{"rendered":"How to get the size of Rust types with -Zprint-type-sizes"},"content":{"rendered":"<p>When optimizing Rust code it&#8217;s sometimes useful to know how big a type is, i.e. how many bytes it takes up in memory. <code>std::mem::size_of<\/code> 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 <a href=\"https:\/\/github.com\/rust-lang\/rust\/pull\/37445\">one variant that is much bigger than the others<\/a>.<\/p>\n<p>The <code>-Zprint-type-sizes<\/code> option does exactly this. It isn&#8217;t enabled on release versions of rustc, so you&#8217;ll need to a nightly version of rustc. Here is one possible invocation:<\/p>\n<pre>cargo +nightly rustc -- -Zprint-type-sizes<\/pre>\n<p>It will print out details of the size, layout, and alignment of all types in use. For example, for this type:<\/p>\n<pre>enum E {\r\n    A,\r\n    B(i32),\r\n    C(u64, u8, u64, u8),\r\n    D(Vec&lt;u32&gt;),\r\n}<\/pre>\n<p>it prints the following, plus info about a few built-in types:<\/p>\n<pre>print-type-size type: `E`: 32 bytes, alignment: 8 bytes\r\nprint-type-size     discriminant: 1 bytes\r\nprint-type-size     variant `A`: 0 bytes\r\nprint-type-size     variant `B`: 7 bytes\r\nprint-type-size         padding: 3 bytes\r\nprint-type-size         field `.0`: 4 bytes, alignment: 4 bytes\r\nprint-type-size     variant `C`: 23 bytes\r\nprint-type-size         field `.1`: 1 bytes\r\nprint-type-size         field `.3`: 1 bytes\r\nprint-type-size         padding: 5 bytes\r\nprint-type-size         field `.0`: 8 bytes, alignment: 8 bytes\r\nprint-type-size         field `.2`: 8 bytes\r\nprint-type-size     variant `D`: 31 bytes\r\nprint-type-size         padding: 7 bytes\r\nprint-type-size         field `.0`: 24 bytes, alignment: 8 bytes<\/pre>\n<p>It shows:<\/p>\n<ul>\n<li>the size and alignment of the type;<\/li>\n<li>for enums, the size of the discriminant;<\/li>\n<li>for enums, the size of each variant;<\/li>\n<li>the size, alignment, and ordering of all fields (note that the compiler has reordered variant <code>C<\/code>&#8216;s fields to minimize the size of <code>E<\/code>);<\/li>\n<li>the size and location of all padding.<\/li>\n<\/ul>\n<p>Every detail you could possibly want is there. Brilliant!<\/p>\n<p>For rustc developers, there&#8217;s an extra-special trick for getting the size of a type within rustc itself. Put code like this into a file <code>a.rs<\/code>:<\/p>\n<pre>#![feature(rustc_private)]\r\nextern crate syntax;\r\nuse syntax::ast::Expr;\r\nfn main() {\r\n    let _x = std::mem::size_of::&lt;Expr&gt;();\r\n}<\/pre>\n<p>and then compile it like this:<\/p>\n<pre>RUSTC_BOOTSTRAP=1 rustc -Zprint-type-sizes a.rs<\/pre>\n<p>I won&#8217;t pretend to understand how it works, but the use of <code>rustc_private<\/code> and <code>RUSTC_BOOTSTRAP<\/code> somehow let you see inside rustc while using it, rather than while compiling it. I have used this trick for PRs such as <a href=\"https:\/\/github.com\/rust-lang\/rust\/pull\/55346\">this one<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When optimizing Rust code it&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":139,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4544,311,617,16179],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/3197"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/users\/139"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/comments?post=3197"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/3197\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/media?parent=3197"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/categories?post=3197"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/tags?post=3197"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}