Rustのオプションタイプのオーバーヘッドは何ですか?


84

Rustでは、参照がnullになることはないため、リンクリストなど、実際にnullが必要な場合は、次のOptionタイプを使用します。

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

単純なポインタと比較して、メモリ割り当てと逆参照の手順に関して、これにはどのくらいのオーバーヘッドが含まれますか?コンパイラ/ランタイムに、同じ構造を使用して非コアライブラリに自分でOption実装Optionしたりenum、ポインタをベクトルでラップしたりする場合よりも、コストをかけずに、またはコストを抑えた「魔法」がありますか?

回答:


87

はい、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

なお&i32Box&[i32]Vec<i32>すべての使用内部の非NULL可能ポインタの最適化Option


38
さらに、この最適化はすべての「Option-like」列挙型で行われるため、ユーザー定義のに対しても機能しますOption
Paul Stansifer 2013年

3
また、この最適化は積み重ねることができないことに注意してください。これは、例の最後の行で確認できます。Okのタイプを()として指定すると、その特定の結果タイプは「列挙型のようなオプション」になるため、オプションレベルで最適化することはできません。しかし、試してみるとResult<i32, i32>、最適化が再び適用されていることがわかります。
Pajn

4
@Pajn少なくとも2020年3月の時点では、このタイプの最適化、無効なバイナリ表現が十分にある限り、積み重ねることできるようです。もちろん、null許容でないポインタには、通常、無効なバイナリ表現が1つだけあります。
Vaelus
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.