Durante muchos años, las aplicaciones .NET funcionaron utilizando un modelo basado en JIT (Just-In-Time Compilation).
Esto significa que el código C# no se ejecuta directamente como código máquina, sino que primero se compila a un lenguaje intermedio llamado IL (Intermediate Language), y luego el runtime de .NET lo convierte a código nativo en tiempo de ejecución.
Este modelo funciona muy bien… pero tiene costos:
- startup más lento
- mayor consumo de memoria
- necesidad de instalar el runtime
- contenedores más pesados
Con la llegada del cloud, Kubernetes y serverless, estos problemas comenzaron a ser cada vez más importantes.
Para resolverlos, Microsoft introdujo Native AOT.
Native AOT (Ahead-Of-Time Compilation) es una tecnología de .NET que permite compilar una aplicación directamente a código máquina nativo.
En lugar de:
C# -> IL -> JIT -> Código Máquina
tenemos:
C# -> IL -> Código Máquina Nativo
El resultado es un ejecutable standalone que no necesita el runtime de .NET instalado en la máquina destino.
Conceptualmente, es muy similar a:
- GraalVM
- Go
- Rust
- Zig
Crearemos una aplicación Native AOT
Paso 1: Crear el proyecto
dotnet new console -n HolaNativeAot
cd HolaNativeAot
Paso 2: Modificar el .csproj
Agregamos:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
El archivo queda algo así:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<PublishAot>true</PublishAot>
</PropertyGroup>
</Project>
Paso 3: Compilar
en Windows
dotnet publish -c Release -r win-x64
en Linux
dotnet publish -c Release -r linux-x64
Se genera algo similar a:
bin/Release/net9.0/linux-x64/publish/
Y dentro encontraremos un ejecutable nativo:
HolaNativeAot
o en Windows:
HolaNativeAot.exe
¿Qué ventajas tiene?
Al no existir JIT:
- a aplicación arranca casi instantáneamente
- ideal para serverless
- ideal para microservicios
Menor consumo de memoria, porque:
- no hay compilación runtime
- menos metadata
- runtime reducido
No hace falta instalar .NET.
El ejecutable ya contiene todo lo necesario.
Native AOT funciona muy bien junto con Docker.
Podemos generar imágenes muy livianas y rápidas de iniciar.
No todo es perfecto.
Native AOT necesita saber en tiempo de compilación qué código será utilizado.
Pero reflection rompe esa idea.
Ejemplo:
var type = Type.GetType("MiClase");
Activator.CreateInstance(type);
El compilador no puede garantizar que ese tipo será usado.
Entonces puede eliminarlo durante el trimming.
Native AOT utiliza una técnica llamada: IL Trimming
El compilador elimina código que considera innecesario.
Muy parecido al concepto de: Closed World Assumption utilizado por GraalVM.
Las librerías más dinámicas suelen tener problemas.
Por ejemplo:
- reflection pesada
- generación dinámica de código
- plugins
- proxies dinámicos
- serializers mágicos
Native AOT funciona especialmente bien con:
- Minimal APIs
- gRPC
- Workers
- herramientas CLI
- microservicios simples
ASP.NET Core tiene soporte parcial para Native AOT.
Se complica si usamos :
- MVC tradicional
- Razor Pages dinámicas
- plugins
- reflection intensiva
Existe también: ReadyToRun (R2R)
Se activa con:
<PublishReadyToRun>true</PublishReadyToRun>
No elimina completamente el JIT, pero mejora considerablemente el startup.
Sería una especie de “semi-AOT”.
Native AOT aparece en un contexto muy concreto:
- Kubernetes
- containers efímeros
- serverless
- autoscaling
- cold starts
En estos escenarios:
- arrancar rápido importa
- consumir menos RAM importa
- tener imágenes pequeñas importa
El modelo JIT sigue siendo excelente para:
- aplicaciones grandes
- desktop
- sistemas dinámicos
- frameworks complejos
- escenarios con mucha reflection
Native AOT está pensado principalmente para:
- cloud-native
- microservicios
- serverless
- APIs livianas
- herramientas CLI
Native AOT representa uno de los cambios más importantes en la evolución moderna de .NET.
donde el resultado final es:
- un único binario
- startup instantáneo
- menor consumo de memoria
- deploy extremadamente simple
Sin embargo, también obliga a abandonar parte de la flexibilidad dinámica que históricamente caracterizó a plataformas como .NET y Java.
Y justamente ahí es donde comienza uno de los debates más interesantes del desarrollo moderno: ¿El futuro es AOT o JIT?

No hay comentarios.:
Publicar un comentario