diff --git a/AyCode.Core.Serializers.Console/Benchmarks/AcBinaryBenchmark.cs b/AyCode.Core.Serializers.Console/Benchmarks/AcBinaryBenchmark.cs
new file mode 100644
index 0000000..e77a187
--- /dev/null
+++ b/AyCode.Core.Serializers.Console/Benchmarks/AcBinaryBenchmark.cs
@@ -0,0 +1,46 @@
+using AyCode.Core.Serializers.Binaries;
+using AyCode.Core.Tests.TestModels;
+using System.Runtime.CompilerServices;
+
+namespace AyCode.Core.Serializers.Console.Benchmarks;
+
+///
+/// AcBinary benchmark, Byte[] I/O mode. The headline AcBinary row in every cell — compared
+/// against as the SOTA baseline.
+///
+internal sealed class AcBinaryBenchmark : ISerializerBenchmark
+{
+ private readonly TestOrder _order;
+ private readonly AcBinarySerializerOptions _options;
+ private readonly byte[] _serialized;
+
+ public string Engine => Configuration.EngineAcBinary;
+ public string IoMode => Configuration.IoByteArray;
+ public string DispatchMode => _options.UseGeneratedCode ? Configuration.ModeSGen : Configuration.ModeRuntime;
+ public string OptionsPreset { get; }
+ public int SerializedSize => _serialized.Length;
+ public long SetupSerializeAllocBytes => 0;
+ public long SetupDeserializeAllocBytes => 0;
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options);
+
+ public AcBinaryBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
+ {
+ _order = order;
+ _options = options;
+ OptionsPreset = optionsPreset;
+ _serialized = AcBinarySerializer.Serialize(order, options);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Serialize() => AcBinarySerializer.Serialize(_order, _options);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Deserialize() => AcBinaryDeserializer.Deserialize(_serialized, _options);
+
+ public bool VerifyRoundTrip()
+ {
+ var bytes = AcBinarySerializer.Serialize(_order, _options);
+ var roundTripped = AcBinaryDeserializer.Deserialize(bytes, _options);
+ return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
+ }
+}
diff --git a/AyCode.Core.Serializers.Console/Benchmarks/BenchmarkOptions.cs b/AyCode.Core.Serializers.Console/Benchmarks/BenchmarkOptions.cs
new file mode 100644
index 0000000..7050fdc
--- /dev/null
+++ b/AyCode.Core.Serializers.Console/Benchmarks/BenchmarkOptions.cs
@@ -0,0 +1,55 @@
+using AyCode.Core.Serializers.Binaries;
+using MemoryPack;
+
+namespace AyCode.Core.Serializers.Console.Benchmarks;
+
+///
+/// Per-engine options-formatting + selection helpers shared by all benchmark rows. Centralizes
+/// the Options-column display string (so the .log / .LLM / console headers stay consistent) and
+/// the MemoryPack WireMode-aligned options selection (so AcBinary FastWire ↔ MemoryPack
+/// UTF-16 comparisons stay apples-to-apples).
+///
+internal static class BenchmarkOptions
+{
+ ///
+ /// Common Options-column formatter for every AcBinary serializer benchmark row. Renders the
+ /// configured options-level value AND the effective attribute-level enable flag side-by-side
+ /// (e.g. Interning=All(opt) | False (attr)) so attribute-suppressed features cannot
+ /// silently mislead. Pass any benchmark-specific extras (e.g. ", BufferSize=4096B")
+ /// in — they are appended after the common fields.
+ ///
+ internal static string BuildAcBinary(AcBinarySerializerOptions options, string extra = "")
+ {
+ // PropertyFilter: opt-side is "Set"/"None" depending on whether a callback is registered (the callback
+ // itself isn't a meaningful display value); attr-side is the cross-type-aggregated bool (true = every
+ // tagged type has the feature enabled, false = at least one type opted out via
+ // [AcBinarySerializable(enablePropertyFilterFeature: false)] → SGen-emit + Runtime hot-loop both gate).
+ var propFilterOpt = options.PropertyFilter == null ? "None" : "Set";
+
+ return $"WireMode={options.WireMode}, " +
+ $"RefHandling={options.ReferenceHandling}(opt) | {Configuration.AttrFlags.refHandling} (attr), " +
+ $"Interning={options.UseStringInterning}(opt) | {Configuration.AttrFlags.internString} (attr), " +
+ $"Metadata={options.UseMetadata}(opt) | {Configuration.AttrFlags.metadata} (attr), " +
+ $"PropertyFilter={propFilterOpt}(opt) | {Configuration.AttrFlags.propertyFilter} (attr), " +
+ $"SGen={options.UseGeneratedCode}, " +
+ $"Compression={options.UseCompression}{extra}";
+ }
+
+ ///
+ /// Returns MemoryPack serializer options aligned with for a fair
+ /// apples-to-apples wire-format comparison:
+ ///
+ /// - → (UTF-8) — both
+ /// engines encode UTF-8, comparison is purely about header / tier / dispatch overhead.
+ /// - → (UTF-16 raw memcpy) —
+ /// both engines write UTF-16 raw bytes, so wire-size and CPU comparison reflect the same string-encoding family.
+ ///
+ /// Without this alignment the FastWire vs MemPack-default comparison conflates two unrelated dimensions
+ /// (UTF-16 raw vs UTF-8 encoded) and produces a misleading +40% wire-size delta that is structurally
+ /// the encoding-family difference, NOT an AcBinary-specific overhead.
+ ///
+ internal static MemoryPackSerializerOptions GetMemPack() =>
+ Configuration.SelectedWireMode == WireMode.Fast
+ ? MemoryPackSerializerOptions.Utf16
+ : MemoryPackSerializerOptions.Default;
+}
diff --git a/AyCode.Core.Serializers.Console/Benchmarks/MemoryPackBenchmark.cs b/AyCode.Core.Serializers.Console/Benchmarks/MemoryPackBenchmark.cs
new file mode 100644
index 0000000..52444e3
--- /dev/null
+++ b/AyCode.Core.Serializers.Console/Benchmarks/MemoryPackBenchmark.cs
@@ -0,0 +1,47 @@
+using AyCode.Core.Tests.TestModels;
+using MemoryPack;
+using System.Runtime.CompilerServices;
+
+namespace AyCode.Core.Serializers.Console.Benchmarks;
+
+///
+/// MemoryPack benchmark, Byte[] I/O mode. The SOTA baseline AcBinary is compared against in every
+/// cell. WireMode-aligned options via so Compact ↔ UTF-8
+/// and FastWire ↔ UTF-16 are apples-to-apples on the string-encoding axis.
+///
+internal sealed class MemoryPackBenchmark : ISerializerBenchmark
+{
+ private readonly TestOrder _order;
+ private readonly MemoryPackSerializerOptions _options;
+ private readonly byte[] _serialized;
+
+ public string Engine => Configuration.EngineMemoryPack;
+ public string IoMode => Configuration.IoByteArray;
+ public string DispatchMode => Configuration.ModeSGen; // MemoryPack always uses [MemoryPackable] source-generated formatters
+ public string OptionsPreset { get; }
+ public int SerializedSize => _serialized.Length;
+ public long SetupSerializeAllocBytes => 0;
+ public long SetupDeserializeAllocBytes => 0;
+ public string? OptionsDescription => $"StringEncoding={_options.StringEncoding}";
+
+ public MemoryPackBenchmark(TestOrder order, string optionsPreset)
+ {
+ _order = order;
+ OptionsPreset = optionsPreset;
+ _options = BenchmarkOptions.GetMemPack();
+ _serialized = MemoryPackSerializer.Serialize(order, _options);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Serialize() => MemoryPackSerializer.Serialize(_order, _options);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Deserialize() => MemoryPackSerializer.Deserialize(_serialized, _options);
+
+ public bool VerifyRoundTrip()
+ {
+ var bytes = MemoryPackSerializer.Serialize(_order, _options);
+ var roundTripped = MemoryPackSerializer.Deserialize(bytes, _options);
+ return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
+ }
+}
diff --git a/AyCode.Core.Serializers.Console/Benchmarks/MessagePackBenchmark.cs b/AyCode.Core.Serializers.Console/Benchmarks/MessagePackBenchmark.cs
new file mode 100644
index 0000000..7f4e2b0
--- /dev/null
+++ b/AyCode.Core.Serializers.Console/Benchmarks/MessagePackBenchmark.cs
@@ -0,0 +1,58 @@
+#if !AYCODE_NATIVEAOT
+using AyCode.Core.Tests.TestModels;
+using MessagePack;
+using MessagePack.Resolvers;
+using System.Runtime.CompilerServices;
+
+namespace AyCode.Core.Serializers.Console.Benchmarks;
+
+///
+/// MessagePack benchmark, Byte[] I/O mode. Excluded from NativeAOT build because v3's StandardResolver
+/// falls back to DynamicGenericResolver for closed-generic types (List<TestOrderItem> et al.),
+/// which uses Activator.CreateInstance on formatter types the AOT trimmer drops →
+/// MissingMethodException at runtime. Available for regular JIT runs (dotnet run) only.
+///
+internal sealed class MessagePackBenchmark : ISerializerBenchmark
+{
+ private readonly TestOrder _order;
+ private readonly MessagePackSerializerOptions _options;
+ private readonly byte[] _serialized;
+
+ public string Engine => Configuration.EngineMessagePack;
+ public string IoMode => Configuration.IoByteArray;
+ public string DispatchMode => Configuration.ModeSGen; // MessagePack uses [MessagePackObject] source-generated formatters (StandardResolver)
+ public string OptionsPreset { get; }
+ public int SerializedSize => _serialized.Length;
+ public long SetupSerializeAllocBytes => 0;
+ public long SetupDeserializeAllocBytes => 0;
+ public string OptionsDescription { get; }
+
+ public MessagePackBenchmark(TestOrder order, string optionsPreset)
+ {
+ _order = order;
+ OptionsPreset = optionsPreset;
+
+ //_options = ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.None);
+ //_options = ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.Lz4Block);
+ _options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.None);
+
+ var isContractless = _options.Resolver is ContractlessStandardResolver;
+ OptionsDescription = $"Mode={( isContractless ? "Contractless" : "ContractBased")}, Compression={_options.Compression}";
+
+ _serialized = MessagePackSerializer.Serialize(order, _options);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Serialize() => MessagePackSerializer.Serialize(_order, _options);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Deserialize() => MessagePackSerializer.Deserialize(_serialized, _options);
+
+ public bool VerifyRoundTrip()
+ {
+ var bytes = MessagePackSerializer.Serialize(_order, _options);
+ var roundTripped = MessagePackSerializer.Deserialize(bytes, _options);
+ return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
+ }
+}
+#endif
diff --git a/AyCode.Core.Serializers.Console/Benchmarks/SystemTextJsonBenchmark.cs b/AyCode.Core.Serializers.Console/Benchmarks/SystemTextJsonBenchmark.cs
new file mode 100644
index 0000000..2acca54
--- /dev/null
+++ b/AyCode.Core.Serializers.Console/Benchmarks/SystemTextJsonBenchmark.cs
@@ -0,0 +1,54 @@
+using AyCode.Core.Tests.TestModels;
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+
+namespace AyCode.Core.Serializers.Console.Benchmarks;
+
+///
+/// System.Text.Json benchmark, String I/O mode. Reference comparison — uses reflection-based metadata
+/// (no source-generator opt-in here). Typically NOT in the active suite (commented out in
+/// BenchmarkLoop.CreateSerializers); ranks far behind binary serializers on µs/op but provides
+/// a familiar JSON baseline when needed.
+///
+internal sealed class SystemTextJsonBenchmark : ISerializerBenchmark
+{
+ private readonly TestOrder _order;
+ private readonly JsonSerializerOptions _options;
+ private readonly string _serialized;
+ private readonly byte[] _serializedUtf8;
+
+ public string Engine => Configuration.EngineSystemTextJson;
+ public string IoMode => Configuration.IoString;
+ public string DispatchMode => Configuration.ModeRuntime; // System.Text.Json default uses reflection-based metadata (no source generator opt-in here)
+ public string OptionsPreset { get; }
+ public int SerializedSize => _serializedUtf8.Length;
+ public long SetupSerializeAllocBytes => 0;
+ public long SetupDeserializeAllocBytes => 0;
+
+ public SystemTextJsonBenchmark(TestOrder order, string optionsPreset)
+ {
+ _order = order;
+ OptionsPreset = optionsPreset;
+ _options = new JsonSerializerOptions
+ {
+ WriteIndented = false,
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
+ ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles
+ };
+ _serialized = JsonSerializer.Serialize(order, _options);
+ _serializedUtf8 = Configuration.Utf8NoBom.GetBytes(_serialized);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Serialize() => JsonSerializer.Serialize(_order, _options);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void Deserialize() => JsonSerializer.Deserialize(_serialized, _options);
+
+ public bool VerifyRoundTrip()
+ {
+ var json = JsonSerializer.Serialize(_order, _options);
+ var roundTripped = JsonSerializer.Deserialize(json, _options);
+ return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
+ }
+}
diff --git a/AyCode.Core.Serializers.Console/Program.cs b/AyCode.Core.Serializers.Console/Program.cs
index 49cec85..19501ed 100644
--- a/AyCode.Core.Serializers.Console/Program.cs
+++ b/AyCode.Core.Serializers.Console/Program.cs
@@ -35,66 +35,7 @@ namespace AyCode.Core.Serializers.Console;
public static class Program
{
// Configuration (constants, mutable state, attribute-flag aggregation) → Configuration.cs
-
- ///
- /// Common Options-column formatter for every AcBinary serializer benchmark row. Renders the
- /// configured options-level value AND the effective attribute-level enable flag side-by-side
- /// (e.g. Interning=All(opt) | False (attr)) so attribute-suppressed features cannot
- /// silently mislead. Pass any benchmark-specific extras (e.g. ", BufferSize=4096B")
- /// in — they are appended after the common fields.
- ///
- private static string BuildAcBinaryOptionsDescription(AcBinarySerializerOptions options, string extra = "")
- {
- // PropertyFilter: opt-side is "Set"/"None" depending on whether a callback is registered (the callback
- // itself isn't a meaningful display value); attr-side is the cross-type-aggregated bool (true = every
- // tagged type has the feature enabled, false = at least one type opted out via
- // [AcBinarySerializable(enablePropertyFilterFeature: false)] → SGen-emit + Runtime hot-loop both gate).
- var propFilterOpt = options.PropertyFilter == null ? "None" : "Set";
-
- return $"WireMode={options.WireMode}, " +
- $"RefHandling={options.ReferenceHandling}(opt) | {Configuration.AttrFlags.refHandling} (attr), " +
- $"Interning={options.UseStringInterning}(opt) | {Configuration.AttrFlags.internString} (attr), " +
- $"Metadata={options.UseMetadata}(opt) | {Configuration.AttrFlags.metadata} (attr), " +
- $"PropertyFilter={propFilterOpt}(opt) | {Configuration.AttrFlags.propertyFilter} (attr), " +
- $"SGen={options.UseGeneratedCode}, " +
- $"Compression={options.UseCompression}{extra}";
- }
-
- ///
- /// Returns MemoryPack serializer options aligned with for a fair
- /// apples-to-apples wire-format comparison:
- ///
- /// - → (UTF-8) — both
- /// engines encode UTF-8, comparison is purely about header / tier / dispatch overhead.
- /// - → (UTF-16 raw memcpy) —
- /// both engines write UTF-16 raw bytes, so wire-size and CPU comparison reflect the same string-encoding family.
- ///
- /// Without this alignment the FastWire vs MemPack-default comparison conflates two unrelated dimensions
- /// (UTF-16 raw vs UTF-8 encoded) and produces a misleading +40% wire-size delta that is structurally
- /// the encoding-family difference, NOT an AcBinary-specific overhead.
- ///
- private static MemoryPackSerializerOptions GetMemPackOptions() =>
- Configuration.SelectedWireMode == WireMode.Fast
- ? MemoryPackSerializerOptions.Utf16
- : MemoryPackSerializerOptions.Default;
-
- ///
- /// Converts a total-time (in ms across ) into per-operation microseconds.
- /// Formula: totalMs / iterations × 1000. The benchmark stores *TimeMs as the cumulative
- /// median over the timing run; the display layer renders per-op µs to make numbers iteration-count
- /// independent (e.g. switching Configuration.TestIterations 1000 → 100 leaves the displayed µs/op unchanged
- /// — only its sample noise grows). Symmetric with the already-per-op *AllocBytesPerOp fields.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
-
- ///
- /// Converts a total-time (in ms across ) into per-operation microseconds.
- /// Per-op µs is the iter-independent unit: 1000 iter and 50000 iter of the same operation should
- /// produce the same per-op µs (within noise). Necessary because per-cell adaptive iteration makes
- /// iterations a per-row property — there is no longer a single global Configuration.TestIterations to divide by.
- ///
- // Output helpers (PrintResult, SaveResults, OverallStats, FormatMicrosWithRange, etc.) → Output.cs
- // BenchmarkResult DTO → BenchmarkResult.cs
+ // BuildAcBinary + GetMemPack helpers → Benchmarks/BenchmarkOptions.cs
public static void Main(string[] args)
{
@@ -637,141 +578,6 @@ private static List RunBenchmarksForTestData(TestDataSet testDa
#region Serializer Implementations
-internal sealed class AcBinaryBenchmark : ISerializerBenchmark
- {
- private readonly TestOrder _order;
- private readonly AcBinarySerializerOptions _options;
- private readonly byte[] _serialized;
-
- public string Engine => Configuration.EngineAcBinary;
- public string IoMode => Configuration.IoByteArray;
- public string DispatchMode => _options.UseGeneratedCode ? Configuration.ModeSGen : Configuration.ModeRuntime;
- public string OptionsPreset { get; }
- public int SerializedSize => _serialized.Length;
- public long SetupSerializeAllocBytes => 0;
- public long SetupDeserializeAllocBytes => 0;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options);
-
- public AcBinaryBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
- {
- _order = order;
- _options = options;
- OptionsPreset = optionsPreset;
- _serialized = AcBinarySerializer.Serialize(order, options);
-
- //_options.UseCompression = Lz4CompressionMode.Block;
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Serialize()
- {
- AcBinarySerializer.Serialize(_order, _options);
-
- //if (_options.ReferenceHandling != ReferenceHandlingMode.None || _options.UseStringInterning != StringInterningMode.None)
- //{
- // AcBinarySerializer.ScanOnly(_order, _options);
- //}
- //else AcBinarySerializer.Serialize(_order, _options);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Deserialize() => AcBinaryDeserializer.Deserialize(_serialized, _options);
-
- public bool VerifyRoundTrip()
- {
- var bytes = AcBinarySerializer.Serialize(_order, _options);
- var roundTripped = AcBinaryDeserializer.Deserialize(bytes, _options);
- return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
- }
- }
-
- internal sealed class MemoryPackBenchmark : ISerializerBenchmark
- {
- private readonly TestOrder _order;
- private readonly MemoryPackSerializerOptions _options;
- private readonly byte[] _serialized;
-
- public string Engine => Configuration.EngineMemoryPack;
- public string IoMode => Configuration.IoByteArray;
- public string DispatchMode => Configuration.ModeSGen; // MemoryPack always uses [MemoryPackable] source-generated formatters
- public string OptionsPreset { get; }
- public int SerializedSize => _serialized.Length;
- public long SetupSerializeAllocBytes => 0;
- public long SetupDeserializeAllocBytes => 0;
- public string? OptionsDescription => $"StringEncoding={_options.StringEncoding}";
-
- public MemoryPackBenchmark(TestOrder order, string optionsPreset)
- {
- _order = order;
- OptionsPreset = optionsPreset;
- _options = GetMemPackOptions();
- _serialized = MemoryPackSerializer.Serialize(order, _options);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Serialize() => MemoryPackSerializer.Serialize(_order, _options);
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Deserialize() => MemoryPackSerializer.Deserialize(_serialized, _options);
-
- public bool VerifyRoundTrip()
- {
- var bytes = MemoryPackSerializer.Serialize(_order, _options);
- var roundTripped = MemoryPackSerializer.Deserialize(bytes, _options);
- return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
- }
- }
-
-#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.
- internal sealed class MessagePackBenchmark : ISerializerBenchmark
- {
- private readonly TestOrder _order;
- private readonly MessagePackSerializerOptions _options;
- private readonly byte[] _serialized;
-
- public string Engine => Configuration.EngineMessagePack;
- public string IoMode => Configuration.IoByteArray;
- public string DispatchMode => Configuration.ModeSGen; // MessagePack uses [MessagePackObject] source-generated formatters (StandardResolver)
- public string OptionsPreset { get; }
- public int SerializedSize => _serialized.Length;
- public long SetupSerializeAllocBytes => 0;
- public long SetupDeserializeAllocBytes => 0;
- public string OptionsDescription { get; }
-
- public MessagePackBenchmark(TestOrder order, string optionsPreset)
- {
- _order = order;
- OptionsPreset = optionsPreset;
-
- //_options = ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.None);
- //_options = ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.Lz4Block);
- _options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.None);
-
- var isContractless = _options.Resolver is ContractlessStandardResolver;
- OptionsDescription = $"Mode={( isContractless ? "Contractless" : "ContractBased")}, Compression={_options.Compression}";
-
- _serialized = MessagePackSerializer.Serialize(order, _options);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Serialize() => MessagePackSerializer.Serialize(_order, _options);
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Deserialize() => MessagePackSerializer.Deserialize(_serialized, _options);
-
- public bool VerifyRoundTrip()
- {
- var bytes = MessagePackSerializer.Serialize(_order, _options);
- var roundTripped = MessagePackSerializer.Deserialize(bytes, _options);
- return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
- }
- }
-#endif
-
///
/// Benchmarks AcBinary via the IBufferWriter overload with a pre-allocated, reused ArrayBufferWriter.
/// Realistic IBufferWriter usage pattern: caller owns + reuses the writer (zero alloc per call after warmup).
@@ -796,7 +602,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public int SerializedSize => _serialized.Length;
public long SetupSerializeAllocBytes => 0;
public long SetupDeserializeAllocBytes => 0;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options, $", BufferSize={_options.BufferWriterChunkSize}B");
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options, $", BufferSize={_options.BufferWriterChunkSize}B");
public AcBinaryFreshBufferWriterBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -896,7 +702,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public long SetupSerializeAllocBytes { get; }
public long SetupDeserializeAllocBytes { get; }
public bool IsRoundTripOnly => true;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=NamedPipe(long-lived,multiMessage,2-task)");
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=NamedPipe(long-lived,multiMessage,2-task)");
public AcBinaryNamedPipeBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -1111,7 +917,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public long SetupSerializeAllocBytes { get; }
public long SetupDeserializeAllocBytes { get; }
public bool IsRoundTripOnly => true;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=Pipe(in-memory,multiMessage,2-task)");
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=Pipe(in-memory,multiMessage,2-task)");
public AcBinaryInMemoryPipeBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -1297,7 +1103,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public long SetupSerializeAllocBytes { get; }
public long SetupDeserializeAllocBytes { get; }
public bool IsRoundTripOnly => true;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=NamedPipe(raw,2-task)");
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=NamedPipe(raw,2-task)");
public AcBinaryNamedPipeRawByteArrayBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -1494,7 +1300,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public long SetupSerializeAllocBytes { get; }
public long SetupDeserializeAllocBytes { get; }
public bool IsRoundTripOnly => true;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=in-memory(raw,2-task)");
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options, $", BufferSize={_options.BufferWriterChunkSize}B, Transport=in-memory(raw,2-task)");
public AcBinaryInMemoryRawByteArrayBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -1638,7 +1444,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
{
_order = order;
OptionsPreset = optionsPreset;
- _options = GetMemPackOptions();
+ _options = BenchmarkOptions.GetMemPack();
_serialized = MemoryPackSerializer.Serialize(order, _options);
}
@@ -1677,7 +1483,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
public int SerializedSize => _serialized.Length;
public long SetupSerializeAllocBytes { get; }
public long SetupDeserializeAllocBytes => 0;
- public string OptionsDescription => BuildAcBinaryOptionsDescription(_options);
+ public string OptionsDescription => BenchmarkOptions.BuildAcBinary(_options);
public AcBinaryBufferWriterBenchmark(TestOrder order, AcBinarySerializerOptions options, string optionsPreset)
{
@@ -1745,7 +1551,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
{
_order = order;
OptionsPreset = optionsPreset;
- _options = GetMemPackOptions();
+ _options = BenchmarkOptions.GetMemPack();
_serialized = MemoryPackSerializer.Serialize(order, _options);
// Serialize-side setup only — see AcBinaryBufferWriterBenchmark for the full rationale.
@@ -1777,50 +1583,7 @@ internal sealed class AcBinaryBenchmark : ISerializerBenchmark
}
}
- internal sealed class SystemTextJsonBenchmark : ISerializerBenchmark
- {
- private readonly TestOrder _order;
- private readonly JsonSerializerOptions _options;
- private readonly string _serialized;
- private readonly byte[] _serializedUtf8;
-
- public string Engine => Configuration.EngineSystemTextJson;
- public string IoMode => Configuration.IoString;
- public string DispatchMode => Configuration.ModeRuntime; // System.Text.Json default uses reflection-based metadata (no source generator opt-in here)
- public string OptionsPreset { get; }
- public int SerializedSize => _serializedUtf8.Length;
- public long SetupSerializeAllocBytes => 0;
- public long SetupDeserializeAllocBytes => 0;
-
- public SystemTextJsonBenchmark(TestOrder order, string optionsPreset)
- {
- _order = order;
- OptionsPreset = optionsPreset;
- _options = new JsonSerializerOptions
- {
- WriteIndented = false,
- DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
- ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles
- };
- _serialized = JsonSerializer.Serialize(order, _options);
- _serializedUtf8 = Configuration.Utf8NoBom.GetBytes(_serialized);
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Serialize() => JsonSerializer.Serialize(_order, _options);
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- public void Deserialize() => JsonSerializer.Deserialize(_serialized, _options);
-
- public bool VerifyRoundTrip()
- {
- var json = JsonSerializer.Serialize(_order, _options);
- var roundTripped = JsonSerializer.Deserialize(json, _options);
- return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped);
- }
- }
-
- #endregion
+#endregion
// Results / output formatters → Output.cs
// BenchmarkResult DTO → BenchmarkResult.cs