La optimización de la colocación de datos en la memoria es una característica clave de Rust que permite ahorrar recursos sin comprometer la seguridad del código. Enum Layout es cómo el compilador coloca las variantes de un enum (con variantes de estructuras o primitivos), así como los propios campos de cualquier estructura. En otros lenguajes, esta optimización suele estar oculta, pero en Rust es muy importante tener en cuenta el orden de los campos para evitar el desperdicio de memoria.
Si el orden de los campos en una estructura se elige de manera desafortunada, debido a las particularidades de alineación de datos, la estructura comenzará a "inflarse" en tamaño. La situación se complica para los enums con datos asociados: el tamaño del enum se define por la variante más grande más el tamaño del discriminador. Ignorar esto conduce a un consumo excesivo de memoria y a una reducción en el rendimiento de la caché del procesador.
Para un empacado efectivo de estructuras y enums, es recomendable colocar primero los campos más "anchos", luego los más estrechos, considerando también los paddings que el compilador puede agregar. Para los enums, se debe elegir la estructura de variantes de manera que no busquen el tamaño máximo a menos que sea justificado.
Ejemplo de código:
struct BadAlign { a: u8, b: u32, c: u16, } struct GoodAlign { b: u32, c: u16, a: u8, } enum Packet { A(u8), B(u32, [u8; 10]), }
Características clave:
¿Se puede hacer que una estructura sea más pequeña simplemente cambiando el orden de los campos?
Sí. Si los campos están en orden de disminución de tamaño, el compilador a menudo reduce la cantidad de paddings, disminuyendo así el tamaño total de la estructura.
println!("{}", std::mem::size_of::<BadAlign>()); // por ejemplo, 12 println!("{}", std::mem::size_of::<GoodAlign>()); // por ejemplo, 8
¿Influye algún orden de los campos en el rendimiento del acceso a ellos?
El orden en sí no afecta la velocidad de acceso a través de los campos. Sin embargo, al recorrer una estructura secuencialmente a bajo nivel (por ejemplo, con instrucciones SIMD o al trabajar con arreglos de estructuras en un bucle), un alineamiento correcto acelera el acceso debido a un mejor uso de la caché.
Si una variante de enum es muy grande, ¿cada instancia de enum ocupará la misma cantidad de memoria, incluso si es de otras variantes?
Sí, el tamaño del enum siempre se determina por el máximo de las variantes más el discriminador. Cualquier Packet ocupará el tamaño de B, incluso si tiene A.
**Caso negativo
En la estructura, los campos son u8, luego u64. Usar en un arreglo de 100000 registros consume hasta un giga de memoria debido a paddings.
Pros:
Contras:
**Caso positivo
Las estructuras fueron clasificadas por el ancho de los campos, en el enum las variantes grandes se sacaron en Box, las pequeñas se dejaron in-place.
Pros:
Contras: