Saltar al contenido principal

Release

  • Cargo tiene 4 perfiles integrados: devreleasetestbench.
  • El perfil se selecciona automáticamente en función del comando que se esté ejecutando si no se especifica uno en la línea de comandos.
  • Cargo solo revisa la configuración del perfil en el Cargo.toml en la raíz del espacio de trabajo.
  • Se ignorarán las configuraciones de perfil definidas en las dependencias.

Resumen

Release personalizado

Cargo.toml

Cargo.toml
[dependencies]
mimalloc = "0.1.46"

[profile.release]
# Maximizar la velocidad de ejecución
codegen-units = 1 # Unidades de código para paralelizar la compilación
lto = "fat" # Análisis a nivel de programa en todo el código

# Minimizar el tamaño del binario
panic = "abort"   # Cierra el programa en caso de pánico
strip = "symbols" # Elimina la información de depuración y símbolos

.cargo/config.toml

.cargo\config.toml
# (Release) Performance
rustflags = ["-C", "target-cpu=native"]

src/main.rs

src\main.rs
// ...

#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[tokio::main]
async fn main() {}

Dockerfile Si se utiliza mimalloc u otros crates como sqlx y rustls que necesitan gcc o musl-tools

Dockerfile
# ...
RUN apt-get update && apt-get install -y musl-tools && rm -rf /var/lib/apt/lists/*

# RUN rustup target add x86_64-unknown-linux-musl
# ...

Release por defecto

  • Se utiliza por cargo install
Cargo.toml
[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...' # Platform-specific.
strip = "none"
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false

Valores que no se modificaron:

[profile.release]
opt-level = 3 # Runtime
debug = false # Runtime
split-debuginfo = '...'
debug-assertions = false # Runtime
overflow-checks = false # Runtime
incremental = false # Buildd
rpath = false # Runtime

Optimizaciones para performance

codegen-units

Determina en cuántas "unidades de generación de código" se dividirá un crate (para paralelizar y acelerar la compilación. Sin embargo, esta división impide que el optimizador realice un análisis global, lo que puede degradar el rendimiento del binario.

  • Esta opción toma un número entero mayor que 0.
  • El valor predeterminado es 256 para compilaciones incrementales y 16 para compilaciones no incrementales.

lto

LTO permite que el optimizador de LLVM realice análisis a nivel de programa en todo el código, lo que suele generar binarios más rápidos y, en muchos casos, más pequeños a costa de un mayor tiempo de enlace.

Las opciones válidas son:

  • false: Realiza una "LTO local thin" que realiza una LTO thin en el contenedor local solo en sus unidades de generación de código . No se realiza una LTO si las unidades de generación de código son 1 o el nivel de opción es 0.
  • true o "fat": Realiza una LTO “fat” que intenta realizar optimizaciones en todas las cajas dentro del gráfico de dependencia.
  • "thin": Realiza una LTO "fina" . Es similar a la "fat", pero tarda mucho menos en ejecutarse y, al mismo tiempo, logra mejoras de rendimiento similares a las de la "fat".
  • "off": Desactiva LTO.

opt-level

  • Un nivel de optimización más alto puede generar un código más rápido en tiempo de ejecución, a costa de tiempos de compilación más largos.
  • Además, un nivel más alto puede modificar y reorganizar el código compilado, lo que dificulta su uso con un depurador.
  • Es recomendable probar con varios ajustes, a veces, 3 podría ser más lento que 2 o que s o z no sean necesariamente binarios más pequeños

Opciones:

  • 0: sin optimizaciones
  • 1: optimizaciones básicas
  • 2: algunas optimizaciones
  • 3: todas las optimizaciones (por defecto)
  • "s": optimizar para tamaño binario
  • "z": optimiza para tamaño binario, pero también desactiva la vectorización de bucle.

overflow-checks

La configuración overflow-checks controla si Rust verifica los desbordamientos aritméticos en operaciones con enteros en tiempo de ejecución.

Para aplicaciones donde la seguridad y la precisión son críticas (como sistemas financieros o médicos), se podría mantener las verificaciones incluso en release, aceptando la pequeña penalización de rendimiento.

Cuando overflow-checks = true:

  • El programa entrará en pánico (crash controlado) si ocurre un desbordamiento de entero
  • Esto ayuda a detectar errores que podrían causar comportamientos inesperados
  • Es muy útil durante el desarrollo y depuración

Cuando overflow-checks = false:

  • Los desbordamientos ocurren silenciosamente, siguiendo el comportamiento de "wrapping" (dar la vuelta)
  • Por ejemplo, para un u8, 255 + 1 = 0
  • Esto suele dar mejor rendimiento porque elimina las verificaciones
  • El valor predeterminado es false para maximizar el rendimiento

Optimizaciones para tamaño del binario

panic

Por defecto, el pánico se maneja con “unwind”, lo que permite capturar y manejar errores, pero añade un coste extra en el tamaño y en el rendimiento.

Las opciones válidas son:

  • "unwind":Desenrolle la pila en caso de pánico.
  • "abort": Terminar el proceso en caso de pánico.

Cuando se establece en "unwind", el valor real depende del valor predeterminado de la plataforma de destino. Por ejemplo, la plataforma NVPTX no admite el desenrollado, por lo que siempre usa "abort".

Con "abort" establece que, ante un pánico, el programa aborta inmediatamente, en lugar de realizar la "desenrollado" de la pila, lo cual reduce overhead.

strip

Indica a rustc que elimine los símbolos o la información de depuración de un binario.

Opciones:

  • "none" o false, predeterminado
  • "debuginfo", elimina la información de depuración del binario.
  • "symbols" o true, elimina la información de depuración y símbolos de la tabla de símbolos.

debug

Controla la cantidad de información de depuración incluida en el binario compilado.

Opciones:

  • 0false, o "none": ninguna información de depuración, valor predeterminado para release
  • "line-directives-only": Solo directivas de información de línea.
  • "line-tables-only": Solo tablas de líneas. Genera la información de depuración mínima para los seguimientos con información de nombre de archivo/número de línea, pero nada más; es decir, no incluye información de variables ni parámetros de función.
  • 1"limited": información de depuración sin información de tipo ni de variable. Genera información más detallada a nivel de módulo que line-tables-only.
  • 2true, o "full": información de depuración completa, predeterminada para dev

split-debuginfo

Controla si la información de depuración, si se genera, se coloca en el mismo ejecutable o junto a él.

El valor predeterminado para esta opción es unpacked en macOS para los perfiles que tienen habilitada la información de depuración.

Opciones:

  • off Esta es la opción predeterminada para plataformas con binarios ELF y windows-gnu (no Windows MSVC ni macOS). Esto suele significar que la información de depuración de DWARF se puede encontrar en el artefacto final, en secciones del ejecutable. Esta opción no es compatible con Windows MSVC. En macOS, esta opción impide la ejecución final para dsymutilgenerar información de depuración.

  • packedEsta es la configuración predeterminada para Windows MSVC y macOS. El término "packed" significa que toda la información de depuración se empaqueta en un archivo separado del ejecutable principal. En Windows MSVC, es un archivo *.pdb; en macOS, una carpeta *.dSYM; y en otras plataformas, un archivo *.dwp.

  • unpackedEsto significa que la información de depuración se encontrará en archivos separados para cada unidad de compilación (archivo de objeto). Esto no es compatible con MSVC para Windows. En macOS, esto significa que los archivos de objeto originales contendrán información de depuración. En otras plataformas Unix, esto significa que los archivos *.dwo contendrán información de depuración.

Otros

debug-assertions

Activa o desactiva la compilación condicional cfg(debug_assertions). Las aserciones de depuración incluyen la validación en tiempo de ejecución, disponible únicamente en compilaciones de depuración y desarrollo.

Estas pueden ser funciones demasiado costosas o indeseables en una versión de lanzamiento. Las aserciones de depuración habilitan la macro debug_assert! en la biblioteca estándar.

Cuando debug-assertions = true:

  • Habilita la macro debug_assert! de la biblioteca estándar
  • Activa código condicional marcado con cfg(debug_assertions)
  • Permite validaciones adicionales que solo se ejecutan durante desarrollo

Cuando debug-assertions = false:

  • Las macros debug_assert! no hacen nada (se eliminan en tiempo de compilación)
  • El código condicional con cfg(debug_assertions) no se incluye
  • Elimina estas verificaciones adicionales para mejorar el rendimiento
  • El valor predeterminado es false para maximizar el rendimiento

incremental

Habilita o no la compilación incremental. La compilación incremental hace que rustc guarde información adicional en el disco, que se reutilizará al recompilar el paquete, lo que reduce los tiempos de re-compilación. Esta información adicional se almacena en el directorio target.

Las opciones válidas son:

  • true: activado
  • false: desactivado

La compilación incremental solo se utiliza para miembros del espacio de trabajo y dependencias de “ruta”.

rpath

  • Incrusta una "ruta de tiempo de ejecución" (runtime path) en el ejecutable
  • Esta ruta indica al cargador de programas dónde buscar las bibliotecas compartidas en tiempo de ejecución
  • Permite que el ejecutable encuentre dependencias de bibliotecas compartidas en ubicaciones relativas a su propio directorio

Memalloc

  • Util para código asíncrono
  • Recomendado al usar Tokio
  • Recomendado al compilar en musl

Instalar

cargo add mimalloc

Usar

src/main.rs
// ...

#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[tokio::main]
async fn main() {}

Configuraciones

.cargo\config.toml
[build]
# Performance ===========================================
# Optimización para la CPU nativa
# Sin embargo, esto puede causar problemas de portabilidad
rustflags = ["-C", "target-cpu=native"]

# Para tiempos de compilación más cortos ===============
# Usando mold linker
# Util para compilaciones de debug
# Se debe tener instalado mold
# Solo funciona en Linux y macOS
# rustflags = ["-C", "link-arg=-fuse-ld=mold"]

# Para binarios más pequeños  ==========================
# No guardar información del código fuente en el binario
# Requiere features inestables
# rustflags = ["-Z", "location-detail=none"]