Skip to content

Native AOT

La compilation Native AOT (Ahead-of-Time) permet de compiler votre application RIVORA en code natif, eliminant le besoin du runtime .NET au demarrage. Cela reduit drastiquement le temps de demarrage et l'empreinte memoire.

Qu'est-ce que Native AOT ?

Avec .NET 9, la compilation AOT transforme votre code C# directement en code machine natif au moment de la compilation, au lieu de le compiler en IL (Intermediate Language) qui serait ensuite interprete par le JIT au runtime.

Avantages

MetriqueJIT classiqueNative AOT
Temps de demarrage~800ms~80ms
Memoire au demarrage~120 MB~30 MB
Taille du binaire~5 MB + runtime~15 MB autonome
Premiere requete~200ms~5ms

Cas d'utilisation ideaux

  • Fonctions serverless (Azure Functions, AWS Lambda) ou le cold start est critique
  • Microservices avec demarrage rapide et faible empreinte
  • Conteneurs ou la taille de l'image compte
  • Applications CLI qui doivent demarrer instantanement

Compatibilite RIVORA

RIVORA vise une compatibilite AOT de 89% sur l'ensemble de ses modules. Voici l'etat actuel :

ModuleCompatible AOTNotes
CoreOuiEntierement compatible
SecurityOuiJWT + HMAC compatibles
Caching (Redis)OuiUtilise System.Text.Json
Jobs (Hangfire)NonNecessite reflexion
Export PDFPartielQuestPDF compatible, iText non
GraphQL (HotChocolate)PartielSupport experimental
EF CoreOuiDepuis EF Core 9
MediatROuiAvec source generators
SignalROuiDepuis .NET 9
AI / Semantic KernelPartielEn progression

Activer Native AOT

1. Configurer le projet

Ajoutez dans votre fichier .csproj :

xml
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <PublishAot>true</PublishAot>
    <InvariantGlobalization>false</InvariantGlobalization>
    <StripSymbols>true</StripSymbols>
  </PropertyGroup>
</Project>

2. Publier en AOT

bash
dotnet publish -c Release -r linux-x64

# Ou via la CLI RIVORA
rvr publish --target self-contained --aot

3. Verifier les avertissements

Executez l'analyse de trimming pour detecter les problemes :

bash
dotnet publish -c Release -r linux-x64 /p:PublishAot=true /p:TrimmerSingleWarn=false

Les avertissements IL2XXX et IL3XXX indiquent du code incompatible.

Marquer un module comme AOT-compatible

Pour declarer un module compatible AOT, ajoutez les attributs suivants :

csharp
// Dans AssemblyInfo.cs du module
[assembly: System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("false")]

// Ou dans le .csproj
// <IsAotCompatible>true</IsAotCompatible>

Dans le code du module, utilisez les annotations de trimming :

csharp
using System.Diagnostics.CodeAnalysis;

public class ProductService
{
    // Indique que ce type est preserve pour AOT
    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
    public Type EntityType => typeof(Product);

    // Methode compatible AOT avec source generator JSON
    public string Serialize(Product product)
    {
        return JsonSerializer.Serialize(product, ProductJsonContext.Default.Product);
    }
}

// Source generator pour System.Text.Json (obligatoire en AOT)
[JsonSerializable(typeof(Product))]
[JsonSerializable(typeof(List<Product>))]
[JsonSerializable(typeof(PagedResult<Product>))]
public partial class ProductJsonContext : JsonSerializerContext { }

Patterns a eviter

Ces patterns utilisent la reflexion et ne fonctionnent pas avec AOT :

Reflexion dynamique

csharp
// INTERDIT en AOT
var type = Type.GetType("MyApp.Services.ProductService");
var instance = Activator.CreateInstance(type);

// INTERDIT - reflexion sur les proprietes
var props = typeof(Product).GetProperties();
foreach (var prop in props)
{
    var value = prop.GetValue(entity);
}

Serialisation sans source generator

csharp
// INTERDIT en AOT
var json = JsonSerializer.Serialize(product);
var obj = JsonSerializer.Deserialize<Product>(json);

// INTERDIT - Newtonsoft.Json
var json = JsonConvert.SerializeObject(product);

Dynamic et ExpandoObject

csharp
// INTERDIT en AOT
dynamic obj = new ExpandoObject();
obj.Name = "Test";

// INTERDIT
dynamic result = someService.GetResult();

Patterns recommandes

Source generators pour JSON

csharp
// CORRECT - Utiliser les source generators
[JsonSerializable(typeof(ApiResponse<Product>))]
[JsonSerializable(typeof(ApiResponse<List<Product>>))]
[JsonSerializable(typeof(ErrorResponse))]
public partial class AppJsonContext : JsonSerializerContext { }

// Registration dans Program.cs
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default);
});

Injection de dependances au lieu de la reflexion

csharp
// CORRECT - DI avec interfaces
public interface IEntityMapper<TEntity, TDto>
{
    TDto Map(TEntity entity);
}

// Registration explicite
builder.Services.AddSingleton<IEntityMapper<Product, ProductDto>, ProductMapper>();

Generic math et interfaces statiques

csharp
// CORRECT - Compile-time polymorphism
public interface IValueObject<TSelf> where TSelf : IValueObject<TSelf>
{
    static abstract TSelf Create(string value);
    static abstract bool IsValid(string value);
}

public readonly record struct Email : IValueObject<Email>
{
    public string Value { get; }
    public static Email Create(string value) => new(value);
    public static bool IsValid(string value) => value.Contains('@');
}

Docker avec AOT

Optimisez vos images Docker avec AOT :

dockerfile
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish src/RVR.Framework.Api/RVR.Framework.Api.csproj \
    -c Release -r linux-x64 -o /app/publish

# Runtime stage - pas besoin du runtime .NET !
FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-noble-chiseled
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["./RVR.Framework.Api"]

Comparaison des tailles d'image :

ImageTaille
SDK + runtime classique~800 MB
Runtime classique (chiseled)~120 MB
AOT (runtime-deps chiseled)~45 MB

Diagnostiquer les problemes AOT

Outil d'analyse

bash
# Analyser la compatibilite AOT
dotnet publish -c Release -r linux-x64 /p:PublishAot=true 2>&1 | grep "warning IL"

# Via la CLI RIVORA
rvr ai review --architecture --aot-compat

Avertissements courants

CodeDescriptionSolution
IL2026RequiresUnreferencedCodeAjouter des annotations ou utiliser des source generators
IL2057Type.GetType dynamiqueUtiliser des references de type directes
IL2070Reflexion sur les membresUtiliser DynamicallyAccessedMembers
IL3050RequiresDynamicCodeEviter les generics ouverts au runtime

Etape suivante

  • CI/CD pour integrer AOT dans votre pipeline
  • Docker pour optimiser vos images conteneurs
  • Monitoring pour mesurer les gains de performance

Released under the MIT License.