In Rust, the compiler tries to efficiently place data in memory by using knowledge about alignment and the layout possibilities of structures and enums. This question is particularly relevant in low-level and systems development, where excessive type size can lead to significant memory overhead.
Automatic struct alignment is a feature of most languages, however in Rust, the compiler provides strict guarantees about layout (while allowing for its optimization), and in the case of enums, implements compact storage by pooling memory for all variants while considering the maximum size).
The order and types of fields in a structure or enum affect the final size of the type due to alignment characteristics. Incorrect ordering increases "padding" — unused bytes. With enums that have associated data, the maximum variant determines the size, and certain constructions can make the enum unexpectedly bulky.
Properly specify the order of fields and select types, analyze data sizes using std::mem::size_of. For enums — be more careful with nested structures and pointers.
Example code:
struct Bad { a: u8, // takes 1 byte + 7 bytes of padding b: u64, // takes 8 bytes } struct Good { b: u64, // 8 bytes, alignment at the start a: u8, // 1 byte + 7 bytes of padding at the end }
Size check:
use std::mem::size_of; println!("{}", size_of::<Bad>()); // 16 bytes println!("{}", size_of::<Good>()); // 16 bytes (but padding is now at the end)
For enums:
enum Example { Unit, Num(u32), Pair(u64, u8), } println!("{}", size_of::<Example>()); // size — max(size of variants) + discriminant
Key features:
If you rearrange the u8 and u64 fields in the struct, will the size of the struct change?
No, the overall size will still be a multiple of the alignment of the largest field, but the padding will shift. This is important if the struct is included in another struct or passed to FFI.
Can a small enum have a large memory size?
Yes, if at least one variant contains a large object or reference, the overall size of the enum will correspond to the "heaviest" variant plus discriminant.
Is the layout of structures the same across all platforms?
No, layout and alignment may differ between architectures. For strict control, the repr(C) attribute is used.
#[repr(C)] struct MyFFIStruct { x: u32, y: u8, }
In large collections, an enum with a nested Vec is used, which is rarely encountered but increases the size of the enum tenfold. Memory is wasted.
Pros:
Cons:
The enum is split into several smaller enums, arrays/collections are stored separately or through Box for rare variants, layout is controlled via #[repr(C)]. Size checked using size_of.
Pros:
Cons: