Rust標準ライブラリが提供するヌル許容型 std::option::Option<T> の空間オーバーヘッドについてメモ。[本記事はRust 1.11/Stable準拠]
まとめ:
T
型がポインタ的に振る舞う(有効値が非ゼロと保障できる)場合、ヌルポインタ最適化(null pointer optimization)*1によりOption<T>
型はT
型のサイズに等しい。内部的には値0をNone
、非0値をSome(T)
として扱う。- それ以外の場合(有効値0もとりうる型)の場合、
T
型の保持領域とは別に追加メモリが必要となる。Option<T>
型のサイズはT
型よりも大きくなる。
use std::mem::size_of; fn main() { println!("i32 {} {}", size_of::<i32>(), size_of::<Option<i32>>()); println!("&i32 {} {}", size_of::<&i32>(), size_of::<Option<&i32>>()); println!("Box<i32> {} {}", size_of::<Box<i32>>(), size_of::<Option<Box<i32>>>()); } // i32 4 8 // &i32 8 8 // Box<i32> 8 8
例えば整数型(i32
)に対してはヌルポインタ最適化を適用できないが、参照型(&i32
)やBox型(Box<i32>
)では同最適化によりゼロ・オーバーヘッドが実現される。これは core::nonzero::NonZero とコンパイラ・マジックにより実現される。Rust 1.11/Stable現在、ユーザ定義型にはヌルポインタ最適化を適用できない。
関連URL
- The Rustonomicon, Data Layout, repr(Rust)
- performance - What is the overhead of Rust's Option type? - Stack Overflow
- rust - Can I use the "null pointer optimization" for my own non-pointer types? - Stack Overflow
*1:同名称はRust公式ドキュメント "The Rustonomicon" 中で言及されている。