Qual è il sovraccarico del tipo di opzione di Rust?


88

In Rust, i riferimenti non possono mai essere nulli, quindi nel caso in cui sia effettivamente necessario nullo, come un elenco collegato, si utilizza il Optiontipo:

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

Quanto overhead è coinvolto in questo in termini di allocazione della memoria e passaggi per la dereferenziazione rispetto a un semplice puntatore? C'è qualche "magia" nel compilatore / runtime da rendere a Optioncosto zero o meno costoso che se si implementasse Optionda soli in una libreria non core utilizzando lo stesso enumcostrutto o avvolgendo il puntatore in un vettore?

Risposte:


91

Sì, c'è qualche magia del compilatore che ottimizza Option<ptr>a un singolo puntatore (la maggior parte delle volte).

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>>);
}

Vengono stampate le seguenti dimensioni (su una macchina a 64 bit, quindi i puntatori sono 8 byte):

// 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

Si noti che &i32, Box, &[i32], Vec<i32>tutto l'uso l'ottimizzazione non annullabile puntatore all'interno di una Option!


39
Inoltre, questa ottimizzazione avviene in tutte le Optionenumerazioni " simili", quindi funzionerà anche per una definizione definita dall'utente Option.
Paul Stansifer

4
Notare inoltre che questa ottimizzazione non può essere impilata. Questo può essere visto nell'ultima riga dell'esempio. Quando si specifica il tipo per Ok come (), quel tipo di risultato specifico diventa una "opzione come enum" e quindi non può essere ottimizzato a livello di opzione. Ma se provi con Result<i32, i32>puoi vedere che l'ottimizzazione viene applicata di nuovo.
Pajn

5
@Pajn Sembra che, almeno da marzo 2020, questo tipo di ottimizzazione possa essere impilato a condizione che ci siano abbastanza rappresentazioni binarie altrimenti non valide. Ovviamente, i puntatori non annullabili in genere hanno solo una rappresentazione binaria non valida.
Vaelus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.