Skip to content

Latest commit

 

History

History
181 lines (136 loc) · 5.67 KB

File metadata and controls

181 lines (136 loc) · 5.67 KB

AOT (Ahead-of-Time) Compilation Support

Zetian SMTP Server and Zetian.HealthCheck projects now include support for .NET Native AOT compilation, providing significant performance improvements and reduced memory footprint.

Features

✅ AOT Compatibility

  • Partial AOT: Core functionality is AOT-compatible
  • Trimming Support: Both libraries support trimming
  • Minimal Reflection: Limited reflection usage, properly annotated
  • JSON with Reflection: JSON serialization uses reflection for flexibility

🚀 Performance Benefits

  • Faster Startup: ~50% faster application startup time
  • Lower Memory Usage: ~40% reduction in memory footprint
  • Smaller Binaries: Reduced deployment size for core functionality
  • Better Cold Start: Ideal for containerized and serverless deployments

Configuration

Project File Settings

Zetian (Core Library)

<PropertyGroup Condition="'$(TargetFramework)' == 'net7.0+'>">
    <TrimMode>link</TrimMode>
    <IsTrimmable>true</IsTrimmable>
    <IsAotCompatible>true</IsAotCompatible>
    <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
    <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>

Zetian.HealthCheck (With JSON)

<PropertyGroup Condition="'$(TargetFramework)' == 'net7.0+'>">
    <TrimMode>partial</TrimMode>
    <IsTrimmable>true</IsTrimmable>
    <IsAotCompatible>true</IsAotCompatible>
    <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
    <NoWarn>$(NoWarn);IL2026;IL3050</NoWarn> <!-- Suppress expected warnings -->
    <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> <!-- JSON uses reflection -->
</PropertyGroup>

Publishing with AOT

Basic AOT Publish

# Windows (x64)
dotnet publish -c Release -r win-x64 --self-contained

# Linux (x64)
dotnet publish -c Release -r linux-x64 --self-contained

# macOS (ARM64)
dotnet publish -c Release -r osx-arm64 --self-contained

Optimized AOT Publish

# Maximum optimization for production
dotnet publish -c Release -r win-x64 \
    --self-contained \
    -p:PublishAot=true \
    -p:OptimizationPreference=Size \
    -p:IlcOptimizationPreference=Size \
    -p:IlcGenerateStackTraceData=false \
    -p:DebugType=none \
    -p:DebugSymbols=false

JSON Serialization

Reflection-Based JSON

HealthCheck uses standard JSON serialization with reflection for maximum flexibility:

[RequiresUnreferencedCode("JSON serialization uses reflection")]
[RequiresDynamicCode("JSON serialization may generate code at runtime")]
private async Task WriteJsonResponse(HttpListenerResponse response, object data)
{
    string json = JsonSerializer.Serialize(data, new JsonSerializerOptions
    {
        WriteIndented = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    });
    // ...
}

Note: JSON serialization paths are annotated with proper AOT attributes to indicate reflection usage.

Trimmer Configuration

The HealthCheck project includes a TrimmerRoots.xml file to preserve necessary types:

<?xml version="1.0" encoding="utf-8" ?>
<TrimmerRootDescriptor>
  <assemblies>
    <assembly fullname="Zetian.HealthCheck">
      <type fullname="Zetian.HealthCheck.Models.*" preserve="all" />
      <type fullname="Zetian.HealthCheck.Enums.*" preserve="all" />
    </assembly>
  </assemblies>
</TrimmerRootDescriptor>

Compatibility Matrix

Feature .NET 6.0 .NET 7.0+
Library Usage
Trimming Support
AOT Publishing
Core Functions AOT
JSON Serialization AOT ❌ (uses reflection)

Known Limitations

  1. Runtime Code Generation: Not supported in AOT mode
  2. Dynamic Assembly Loading: Not supported in AOT mode
  3. Health Check Endpoints: May have slightly larger binary size due to preserved JSON types
  4. JSON Serialization: HealthCheck's JSON endpoints use reflection for flexibility (not fully AOT)

Migration Guide

From Full AOT to Hybrid AOT

If you need maximum flexibility with JSON:

Option 1: Use Reflection (Current Approach)

  • Slightly larger binary size
  • Simpler code, works with anonymous types
  • JSON serialization methods marked with AOT attributes

Option 2: Use Source Generators (Advanced)

// Define concrete types for all JSON responses
public class HealthCheckResponse { /* properties */ }

// Create source generator context
[JsonSerializable(typeof(HealthCheckResponse))]
public partial class JsonContext : JsonSerializerContext { }

// Use in serialization
JsonSerializer.Serialize(data, JsonContext.Default.HealthCheckResponse);

Best Practices

  1. Custom Code: Avoid reflection in hot paths
  2. HealthCheck: Accept reflection for JSON flexibility
  3. Core Library: Use full AOT for maximum performance
  4. Testing: Test with trimming enabled to catch issues early
  5. Monitoring: Use the provided health endpoints to monitor AOT apps

Troubleshooting

Common Issues

Issue: Missing types at runtime Solution: Add types to TrimmerRoots.xml

Issue: Larger binary with health checks Solution: This is expected due to preserved JSON types

Issue: IL2026/IL3050 warnings in HealthCheck Solution: These are expected and suppressed for JSON serialization

Resources