2013-05-12 15 views
51

A Rust, i riferimenti non può mai essere nullo, così nel caso in cui hai veramente bisogno nullo, come ad esempio una lista collegata, si utilizza il tipo Option:Qual è il sovraccarico del tipo di opzione di Rust?

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

Quanto testa è coinvolta in questo in termini di memoria allocazione e passaggi alla dereferenziazione rispetto ad un semplice puntatore? C'è del "magico" nel compilatore/runtime per rendere Option esente da costi, o meno costoso che se si dovesse implementare Option da soli in una libreria non core usando lo stesso costrutto enum o avvolgendo il puntatore in un vettore ?

risposta

55

Sì, c'è qualche magia del compilatore che ottimizza Option<ptr> in un singolo puntatore (il più 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>>); 
} 

Le seguenti dimensioni vengono stampate (su una macchina a 64 bit, in modo 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 

noti che &i32, Box, &[i32], Vec<i32> utilizzano tutti il ​​puntatore non annullabile ottimizzazione all'interno di un Option!

+17

Inoltre, questa ottimizzazione si verifica in tutte le enumerazioni di tipo "opzioni", quindi funzionerà anche con un'opzione definita dall'utente. –

6

Questa risposta è ora obsoleta; la discriminante in Option<T> viene ora ottimizzata, laddove possibile.(Il resto delle informazioni fornite sono comunque interessante, però.)

Per ora, un tipo Option occupa la stessa quantità di spazio rispetto a qualsiasi altro tipo enum. Non conosco le specifiche, ma è certamente rappresentato come una sorta di unione discriminata.

La possibilità di modificare la rappresentazione interna per l'ottimizzazione viene presa in considerazione dagli sviluppatori di Rust.

Ecco una relevant discussion on the dev mailing list, pubblicato da Patrick Walton:

sono un po 'restii a impegnarsi per una particolare rappresentazione po' di enumerazioni, dal momento che c'è un sacco di spazio per l'ottimizzazione del compilatore qui. Ad esempio, potremmo voler collassare Option<~int> in un puntatore Null , potremmo voler collassare Result<(),~str> in una stringa annullabile, oppure si potrebbe desiderare di collassare Either<u8,~str> in 1 parola, assumendo che le stringhe possono mai occupare i primi 256 byte dello spazio indirizzo . Ho pensato per un po 'che forse è meglio per dire che il bit pattern delle enumerazioni di Rust non è specificato, per dare a il maggior spazio possibile per giocare con le ottimizzazioni.

+1

Questo non è corretto. (Alcune delle) ottimizzazioni che hai menzionato sono state [implementate] (https://github.com/mozilla/rust/pull/6001). – huon

+1

Bene, come hai detto è corretto per la versione attuale di Rust :-) – barjak

Problemi correlati