diff --git a/AyCode.Core.Serializers.Console/AyCode.Core.Serializers.Console.csproj b/AyCode.Core.Serializers.Console/AyCode.Core.Serializers.Console.csproj
index 39a0534..9654e4d 100644
--- a/AyCode.Core.Serializers.Console/AyCode.Core.Serializers.Console.csproj
+++ b/AyCode.Core.Serializers.Console/AyCode.Core.Serializers.Console.csproj
@@ -21,6 +21,12 @@
truetrue
+
+ $(DefineConstants);AYCODE_NATIVEAOT
+
true
diff --git a/AyCode.Core.Serializers.Console/Program.cs b/AyCode.Core.Serializers.Console/Program.cs
index b756403..292f1fe 100644
--- a/AyCode.Core.Serializers.Console/Program.cs
+++ b/AyCode.Core.Serializers.Console/Program.cs
@@ -4,8 +4,10 @@ using AyCode.Core.Serializers.Binaries;
using AyCode.Core.Tests.Serialization; // DrainFromAsync extension (test-only, used by benchmark)
using AyCode.Core.Tests.TestModels;
using MemoryPack;
+#if !AYCODE_NATIVEAOT
using MessagePack;
using MessagePack.Resolvers;
+#endif
using Microsoft.Extensions.Options;
using System.Buffers;
using System.Diagnostics;
@@ -52,7 +54,9 @@ public static class Program
// Engine identifiers (used in Engine column + comparison logic)
private const string EngineAcBinary = "AcBinary";
private const string EngineMemoryPack = "MemoryPack";
+#if !AYCODE_NATIVEAOT
private const string EngineMessagePack = "MessagePack";
+#endif
private const string EngineSystemTextJson = "System.Text.Json";
// IO mode identifiers (used in IO column + comparison logic)
@@ -557,9 +561,9 @@ public static class Program
new AcBinaryBenchmark(testData.Order, AcBinarySerializerOptions.FastMode, "FastMode"),
// Fastest Byte[] — Runtime path (UseGeneratedCode=false). Same wire/options, no source-generated dispatch.
// Always paired with the SGen variant so every layer can compare the SGen speed-up apples-to-apples.
- // COMMENTED: Reflection.Emit-based dispatch crashes under NativeAOT (PlatformNotSupportedException).
- // Re-enable for JIT-mode benchmarks where SGen-vs-Runtime delta matters.
- //new AcBinaryBenchmark(testData.Order, binaryFastModeNoSgenOption, "FastMode"),
+ // NativeAOT-safe: AcSerializerCommon.Create*Getter/Setter falls back to reflection-based delegates
+ // when RuntimeFeature.IsDynamicCodeSupported is false (slower but works under AOT publish).
+ new AcBinaryBenchmark(testData.Order, binaryFastModeNoSgenOption, "FastMode"),
// Default preset Byte[] — RefHandling=OnlyId (deduplicates IId-shared references on the wire) +
// UseStringInterning=All (deduplicates repeated strings). Showcases the Default preset's wire-size
// and CPU trade-off vs FastMode on the ~20% IId-ref / repeated-string test data.
@@ -602,7 +606,12 @@ public static class Program
// ============================================================
// MessagePack — for legacy comparison
// ============================================================
+#if !AYCODE_NATIVEAOT
+ // MessagePack v3's DynamicGenericResolver uses Activator.CreateInstance on trimmed
+ // ListFormatter et al. — fails under NativeAOT publish with "No parameterless constructor".
+ // Excluded from the AOT build; available for regular JIT runs only.
new MessagePackBenchmark(testData.Order, "ContractBased"),
+#endif
// System.Text.Json (commented — JSON serializer for reference; not in active suite)
//new SystemTextJsonBenchmark(testData.Order, "Default")
@@ -1031,6 +1040,11 @@ public static class Program
}
}
+#if !AYCODE_NATIVEAOT
+ // MessagePack benchmark — excluded from NativeAOT build because v3's StandardResolver falls back
+ // to DynamicGenericResolver for closed-generic types (List et al.), which uses
+ // Activator.CreateInstance on formatter types the AOT trimmer drops → MissingMethodException at runtime.
+ // Available for regular JIT runs (`dotnet run`) only.
private sealed class MessagePackBenchmark : ISerializerBenchmark
{
private readonly TestOrder _order;
@@ -1083,6 +1097,7 @@ public static class Program
return DeepEqualsViaJson(_order, roundTripped);
}
}
+#endif
///
/// Benchmarks AcBinary via the IBufferWriter overload with a pre-allocated, reused ArrayBufferWriter.
diff --git a/AyCode.Core/Serializers/AcSerializerCommon.cs b/AyCode.Core/Serializers/AcSerializerCommon.cs
index 5392ad3..b07e40a 100644
--- a/AyCode.Core/Serializers/AcSerializerCommon.cs
+++ b/AyCode.Core/Serializers/AcSerializerCommon.cs
@@ -465,6 +465,12 @@ public static class AcSerializerCommon
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Func
public static Action