Translate

miércoles, 3 de junio de 2026

¿Qué es Native AOT en .NET?


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