L'optimisation de l'emplacement des données en mémoire est une caractéristique clé de Rust qui permet d'économiser des ressources sans compromettre la sécurité du code. L'Enum Layout est la façon dont le compilateur organise les variantes d'un enum (avec des variantes-structures ou des primitives), ainsi que les champs de n'importe quelle structure. Dans d'autres langages, cette optimisation est souvent cachée, tandis qu'en Rust, il est très important de tenir compte de l'ordre des champs pour éviter le gaspillage de mémoire.
Si l'ordre des champs dans une structure est mal choisi, en raison des particularités de l'alignement des données, la structure commencera à "gonfler" en taille. Pour les enums avec des données associées, la situation se complique : la taille de l'enum est déterminée par la plus grande variante plus la taille du discriminateur. Négliger cela conduit à une consommation de mémoire excessive, réduisant la performance du cache du processeur.
Pour un emballage efficace des structures et des enums, il est conseillé de placer d'abord les champs les plus « larges », puis les plus étroits, et de tenir compte des paddings que le compilateur peut ajouter. Pour les enums, il faut choisir la structure des variantes de manière à ce qu'elles ne tendent pas vers la taille maximale, sauf si cela est justifié.
Exemple de code :
struct BadAlign { a: u8, b: u32, c: u16, } struct GoodAlign { b: u32, c: u16, a: u8, } enum Packet { A(u8), B(u32, [u8; 10]), }
Caractéristiques clés :
Peut-on rendre une structure plus petite simplement en changeant l'ordre des champs ?
Oui. Si les champs sont dans un ordre décroissant de taille, le compilateur réduit souvent le nombre de paddings, diminuant ainsi la taille globale de la structure.
println!("{}", std::mem::size_of::<BadAlign>()); // par exemple, 12 println!("{}", std::mem::size_of::<GoodAlign>()); // par exemple, 8
L'ordre des champs influence-t-il la performance d'accès à ces champs ?
L'ordre en lui-même n'affecte pas la vitesse d'accès aux champs. Cependant, lors d'un parcours séquentiel d'une structure à un niveau bas (par exemple, avec des instructions SIMD ou lors du travail avec des tableaux de structures dans une boucle), un bon alignement accélère l'accès grâce à une meilleure utilisation du cache.
Si une variante de l'enum est très grande, chaque instance de l'enum occupera-t-elle autant de mémoire, même si elle contient d'autres variantes ?
Oui, la taille de l'enum est toujours déterminée par la plus grande des variantes plus le discriminateur. Tout Packet occupera la taille de B, même s'il contient A.
** Cas négatif
Dans une structure, les champs u8, puis u64. Utilisation dans un tableau de 100000 enregistrements consomme jusqu'à un gigaoctet de mémoire en raison des paddings.
Avantages :
Inconvénients :
** Cas positif
Les structures ont été triées par largeur de champs, les grandes variantes de l'enum ont été mises dans un Box, les petites laissées in-place.
Avantages :
Inconvénients :