Q: Rust의 Option 타입은 어떤 오버헤드가 있나요? (번역)

https://stackoverflow.com/questions/16504643/what-is-the-overhead-of-rusts-option-type


질문

Rust에서 참조는 절대 null이 될 수 없지만, null이 실제로 필요할 경우가 많죠.
그래서 아래처럼 Option으로 null을 표현하곤 하는데요.

**struct Element **
**{ **
**    value: i32, **
**    next: Option<Box>, **
**} **

그냥 포인터와 비교하면 메모리 할당이나 역참조에서 얼마나 많은 오버헤드가 발생할까요?

컴파일러나 런타임에 Option의 비용을 없애주는 '매직'이 있는 건가요?
아니면 그냥 동일한 열거형 구성을 사용하거나 포인터를 벡터로 래핑하여 non-core 라이브러리에서 직접 Option을 구현하는 것보다 비용이 적게 드는 수준인가요?



답변

네. Rust 컴파일러는 Option<포인터>를 포인터로 바꿔주는 매ㅡ직을 부립니다. 대부분의 경우에요.

**use std::mem::size_of; **

**macro_rules! show_size **
**{ **
**    (header) => ( **
**        println!("{:<22} {:>4} {}", "Type", "T", "Option"); ); **
**    ($t:ty) => ( println!("{:<22} {:4} {:4}", stringify!($t), size_of::<$t>(), size_of::<Option<$t>>()) ) **
**} **

**fn main() **
**{ **
**    show_size!(header); **
**    show_size!(i32); **
**    show_size!(&i32); **
**    show_size!(Box); **
**    show_size!(&[i32]); **
**    show_size!(Vec); **
**    show_size!(Result<(), Box>); **
}

이건 다음과 같이 출력될 겁니다. 포인터가 8바이트인 64비트 머신에서요.

// As of Rust 1.22.1
Type                                 T             Option
i32                                    4                    8
&i32                                  8                    8
Box                         8                    8
&[i32]                               16                 16
Vec                         24                 24
Result<(), Box>     8                   16

여기서 &i32, Box, &[i32], Vec은 모두 Option 안에 들어가면 non-nullable 포인터 최적화를 사용할 수 있어요!