Rust의 옵션 유형의 오버 헤드는 무엇입니까?


85

Rust에서 참조는 절대 null이 될 수 없으므로 연결 목록과 같이 실제로 null이 필요한 경우에는 다음 Option유형 을 사용합니다 .

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

간단한 포인터와 비교하여 메모리 할당 및 역 참조 단계와 관련하여 얼마나 많은 오버 헤드가 관련됩니까? 컴파일러 / 런타임에 Option비용이 들지 않게 만드는 "마법" 이 있습니까? 아니면 Option동일한 enum구조를 사용하여 비 코어 라이브러리에서 직접 구현 하거나 벡터에 포인터를 래핑하는 것보다 비용이 적게 듭 니까?

답변:


88

예, Option<ptr>단일 포인터로 최적화 하는 컴파일러 마법이 있습니다 (대부분).

use std::mem::size_of;

macro_rules! show_size {
    (header) => (
        println!("{:<22} {:>4}    {}", "Type", "T", "Option<T>");
    );
    ($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<i32>);
    show_size!(&[i32]);
    show_size!(Vec<i32>);
    show_size!(Result<(), Box<i32>>);
}

다음 크기가 인쇄됩니다 (64 비트 시스템에서 포인터는 8 바이트).

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

그 주 &i32, Box, &[i32], Vec<i32>모든 사용 내부 비 - 널 포인터 최적화 Option!


38
또한이 최적화는 모든 " Option유사"열거 형에서 발생하므로 사용자 정의 Option.
Paul Stansifer 2013 년

4
또한이 최적화는 누적 될 수 없습니다. 이것은 예제의 마지막 줄에서 볼 수 있습니다. Ok의 유형을 ()로 지정하면 특정 결과 유형이 "enum과 같은 옵션"이되므로 옵션 수준에서 최적화 할 수 없습니다. 하지만 시도해 Result<i32, i32>보면 최적화가 다시 적용되는 것을 볼 수 있습니다.
Pajn

5
@Pajn 적어도 2020 년 3 월 현재이 유형의 최적화 유효하지 않은 바이너리 표현이 충분하다면 쌓을 있는 것 같습니다. 물론 nullable이 아닌 포인터는 일반적으로 잘못된 이진 표현이 하나만 있습니다.
Vaelus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.