L'ottimizzazione del posizionamento dei dati in memoria è una caratteristica chiave di Rust che consente di risparmiare risorse senza compromettere la sicurezza del codice. Enum Layout è il modo in cui il compilatore posiziona le varianti enum (con varianti-strutture o primitivi) e anche i campi di qualsiasi struttura. In altri linguaggi, tale ottimizzazione è spesso nascosta, mentre in Rust è molto importante tenere conto dell'ordine dei campi per evitare lo spreco di memoria.
Se l'ordine dei campi in una struttura è scelto sfortunatamente, a causa delle peculiarità dell'allineamento dei dati, la struttura inizierà a "gonfiarsi" di dimensione. Per gli enum con dati associati, la situazione si complica: la dimensione dell'enum è determinata dalla variante più grande più la dimensione del discriminatore. Ignorare questo porta a un consumo eccessivo di memoria e riduzione delle prestazioni della cache della CPU.
Per un'imballaggio efficace di strutture e enum, è consigliabile disporre prima i campi "più larghi", poi quelli più stretti e considerare i padding che il compilatore può aggiungere. Per gli enum, è bene scegliere la struttura delle varianti in modo che non tendano alla dimensione massima, se non giustificato.
Esempio di codice:
struct BadAlign { a: u8, b: u32, c: u16, } struct GoodAlign { b: u32, c: u16, a: u8, } enum Packet { A(u8), B(u32, [u8; 10]), }
Caratteristiche chiave:
È possibile rendere una struttura più piccola semplicemente cambiando l'ordine dei campi?
Sì. Se i campi seguono l'ordine di dimensione decrescente, il compilatore spesso riduce il numero di padding, riducendo così la dimensione complessiva della struttura.
println!("{}", std::mem::size_of::<BadAlign>()); // ad esempio, 12 println!("{}", std::mem::size_of::<GoodAlign>()); // ad esempio, 8
Influisce in qualche modo l'ordine dei campi sulle prestazioni di accesso a essi?
L'ordine di per sé non influisce sulla velocità di accesso ai campi. Tuttavia, durante l'iterazione sequenziale della struttura a basso livello (ad esempio, con istruzioni SIMD o lavorando con array di strutture in un ciclo), un corretto allineamento accelera l'accesso grazie a un miglior utilizzo della cache.
Se una variante enum è molto grande, ogni istanza dell'enum occuperà sempre la stessa quantità di memoria, anche se è di altre varianti?
Sì, la dimensione dell'enum è sempre determinata dalla variante massima più il discriminatore. Qualsiasi Packet occuperà la dimensione di B, anche se contiene A.
** Caso negativo
Nella struttura, i campi u8, poi u64. L'utilizzo in un array di 100000 registrazioni consuma fino a un gigabyte di memoria a causa dei padding.
Vantaggi:
Svantaggi:
** Caso positivo
Le strutture sono state ordinate per larghezza dei campi, con varianti grandi degli enum spostate in Box, mentre quelle piccole sono state mantenute in loco.
Vantaggi:
Svantaggi: