Usage of enum-types is inherent in Rust, usually causing additional overhead due to the enum-discriminator. But, there are a number of optimizations that may eliminate this memory overhead. The following is just a cheatsheet. For further reading see https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html
Data-Less and Uninhabited fields
Data containers without data payload or containers over types of “zero byte size” the following optimizations exist.
Introduced by MR https://github.com/rust-lang/rust/pull/45225
Size optimizations implemented so far:
- ignoring uninhabited variants (i.e. containing uninhabited fields), e.g.:
Option<!>
is 0 bytesResult<T, !>
has the same size asT
- using arbitrary niches, not just
0
, to represent a data-less variant, e.g.:Option<bool>
,Option<Option<bool>>
,Option<Ordering>
are all 1 byteOption<char>
is 4 bytes
- using a range of niches to represent multiple data-less variants, e.g.:
enum E { A(bool), B, C, D }
is 1 byte
An integer that is known not to equal zero.
Wrappers as Option<T> or Result<T> over “NonZero” data types may be optimized by the compiler.
For example Option<usize> may occupy up to 16 bytes, using 8 additional bytes for the discriminator to represent a flag such as 0x00 and 0x01. In contrast using the NonZeroUsize as in Option<NonZeroUsize> the memory consumption may shrink to 8 bytes in total. using the unused bit of NonZeroUsize to represent the discriminator of the generic data type Option<T>
See https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html
This enables some memory layout optimization. For example, Option<NonZeroUsize>
is the same size as usize
:
use std::mem::size_of;
assert_eq!(size_of::<Option<core::num::NonZeroUsize>>(), size_of::<usize>());
And analogous to it all other NonZero types https://doc.rust-lang.org/std/num/index.html
Please note, using an optimized Option<NonZeroX>
, its enum-discriminator will be one of the ‘unused’ bit-combinations in the underlying integer representation, for example the bit combination all zero representing state Option::None
.