AyCode.Core/BenchmarkSuite1/SerializationBenchmarks.cs

196 lines
7.6 KiB
C#

using AyCode.Core.Extensions;
using AyCode.Core.Tests.TestModels;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using MessagePack;
using MessagePack.Resolvers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace AyCode.Core.Benchmarks;
/// <summary>
/// Minimal benchmark to test if BenchmarkDotNet works without stack overflow.
/// </summary>
[ShortRunJob]
[MemoryDiagnoser]
public class MinimalBenchmark
{
private byte[] _data = null!;
private string _json = null!;
[GlobalSetup]
public void Setup()
{
// Use very simple data - no circular references
var simpleData = new { Id = 1, Name = "Test", Value = 42.5 };
_json = System.Text.Json.JsonSerializer.Serialize(simpleData);
_data = Encoding.UTF8.GetBytes(_json);
Console.WriteLine($"Setup complete. Data size: {_data.Length} bytes");
}
[Benchmark]
public int GetLength() => _data.Length;
[Benchmark]
public string GetJson() => _json;
}
/// <summary>
/// Binary vs JSON benchmark with simple flat objects (no circular references).
/// </summary>
[ShortRunJob]
[MemoryDiagnoser]
public class SimpleBinaryBenchmark
{
private PrimitiveTestClass _testData = null!;
private byte[] _binaryData = null!;
private string _jsonData = null!;
[GlobalSetup]
public void Setup()
{
_testData = TestDataFactory.CreatePrimitiveTestData();
_binaryData = AcBinarySerializer.Serialize(_testData);
_jsonData = AcJsonSerializer.Serialize(_testData, AcJsonSerializerOptions.WithoutReferenceHandling());
Console.WriteLine($"Binary: {_binaryData.Length} bytes, JSON: {_jsonData.Length} chars");
}
[Benchmark(Description = "Binary Serialize")]
public byte[] SerializeBinary() => AcBinarySerializer.Serialize(_testData);
[Benchmark(Description = "JSON Serialize", Baseline = true)]
public string SerializeJson() => AcJsonSerializer.Serialize(_testData, AcJsonSerializerOptions.WithoutReferenceHandling());
[Benchmark(Description = "Binary Deserialize")]
public PrimitiveTestClass? DeserializeBinary() => AcBinaryDeserializer.Deserialize<PrimitiveTestClass>(_binaryData);
[Benchmark(Description = "JSON Deserialize")]
public PrimitiveTestClass? DeserializeJson() => AcJsonDeserializer.Deserialize<PrimitiveTestClass>(_jsonData, AcJsonSerializerOptions.WithoutReferenceHandling());
}
/// <summary>
/// Complex hierarchy benchmark - AcBinary vs JSON only (no MessagePack to isolate the issue).
/// </summary>
[ShortRunJob]
[MemoryDiagnoser]
[RankColumn]
public class ComplexBinaryBenchmark
{
private TestOrder _testOrder = null!;
private byte[] _acBinaryData = null!;
private string _jsonData = null!;
private AcBinarySerializerOptions _binaryOptions = null!;
private AcJsonSerializerOptions _jsonOptions = null!;
[GlobalSetup]
public void Setup()
{
Console.WriteLine("Creating test data...");
_testOrder = TestDataFactory.CreateBenchmarkOrder(
itemCount: 2,
palletsPerItem: 2,
measurementsPerPallet: 2,
pointsPerMeasurement: 3);
Console.WriteLine($"Created order with {_testOrder.Items.Count} items");
_binaryOptions = AcBinarySerializerOptions.Default;
_jsonOptions = AcJsonSerializerOptions.WithoutReferenceHandling();
Console.WriteLine("Serializing AcBinary...");
_acBinaryData = AcBinarySerializer.Serialize(_testOrder, _binaryOptions);
Console.WriteLine($"AcBinary size: {_acBinaryData.Length} bytes");
Console.WriteLine("Serializing JSON...");
_jsonData = AcJsonSerializer.Serialize(_testOrder, _jsonOptions);
Console.WriteLine($"JSON size: {_jsonData.Length} chars");
var jsonBytes = Encoding.UTF8.GetByteCount(_jsonData);
Console.WriteLine($"\n=== SIZE COMPARISON ===");
Console.WriteLine($"AcBinary: {_acBinaryData.Length,8:N0} bytes ({100.0 * _acBinaryData.Length / jsonBytes:F1}%)");
Console.WriteLine($"JSON: {jsonBytes,8:N0} bytes (100.0%)");
}
[Benchmark(Description = "AcBinary Serialize")]
public byte[] Serialize_AcBinary() => AcBinarySerializer.Serialize(_testOrder, _binaryOptions);
[Benchmark(Description = "JSON Serialize", Baseline = true)]
public string Serialize_Json() => AcJsonSerializer.Serialize(_testOrder, _jsonOptions);
[Benchmark(Description = "AcBinary Deserialize")]
public TestOrder? Deserialize_AcBinary() => AcBinaryDeserializer.Deserialize<TestOrder>(_acBinaryData);
[Benchmark(Description = "JSON Deserialize")]
public TestOrder? Deserialize_Json() => AcJsonDeserializer.Deserialize<TestOrder>(_jsonData, _jsonOptions);
}
/// <summary>
/// Full comparison with MessagePack - separate class to isolate potential issues.
/// </summary>
[ShortRunJob]
[MemoryDiagnoser]
[RankColumn]
public class MessagePackComparisonBenchmark
{
private TestOrder _testOrder = null!;
private byte[] _acBinaryData = null!;
private byte[] _msgPackData = null!;
private string _jsonData = null!;
private AcBinarySerializerOptions _binaryOptions = null!;
private MessagePackSerializerOptions _msgPackOptions = null!;
private AcJsonSerializerOptions _jsonOptions = null!;
[GlobalSetup]
public void Setup()
{
Console.WriteLine("Creating test data...");
_testOrder = TestDataFactory.CreateBenchmarkOrder(
itemCount: 2,
palletsPerItem: 2,
measurementsPerPallet: 2,
pointsPerMeasurement: 3);
_binaryOptions = AcBinarySerializerOptions.Default;
_msgPackOptions = ContractlessStandardResolver.Options.WithCompression(MessagePackCompression.None);
_jsonOptions = AcJsonSerializerOptions.WithoutReferenceHandling();
_acBinaryData = AcBinarySerializer.Serialize(_testOrder, _binaryOptions);
_jsonData = AcJsonSerializer.Serialize(_testOrder, _jsonOptions);
// MessagePack serialization in try-catch to see if it fails
try
{
Console.WriteLine("Serializing MessagePack...");
_msgPackData = MessagePackSerializer.Serialize(_testOrder, _msgPackOptions);
Console.WriteLine($"MessagePack size: {_msgPackData.Length} bytes");
}
catch (Exception ex)
{
Console.WriteLine($"MessagePack serialization failed: {ex.Message}");
_msgPackData = Array.Empty<byte>();
}
var jsonBytes = Encoding.UTF8.GetByteCount(_jsonData);
Console.WriteLine($"\n=== SIZE COMPARISON ===");
Console.WriteLine($"AcBinary: {_acBinaryData.Length,8:N0} bytes ({100.0 * _acBinaryData.Length / jsonBytes:F1}%)");
Console.WriteLine($"MessagePack: {_msgPackData.Length,8:N0} bytes ({100.0 * _msgPackData.Length / jsonBytes:F1}%)");
Console.WriteLine($"JSON: {jsonBytes,8:N0} bytes (100.0%)");
}
[Benchmark(Description = "AcBinary Serialize")]
public byte[] Serialize_AcBinary() => AcBinarySerializer.Serialize(_testOrder, _binaryOptions);
[Benchmark(Description = "MessagePack Serialize", Baseline = true)]
public byte[] Serialize_MsgPack() => MessagePackSerializer.Serialize(_testOrder, _msgPackOptions);
[Benchmark(Description = "AcBinary Deserialize")]
public TestOrder? Deserialize_AcBinary() => AcBinaryDeserializer.Deserialize<TestOrder>(_acBinaryData);
[Benchmark(Description = "MessagePack Deserialize")]
public TestOrder? Deserialize_MsgPack() => MessagePackSerializer.Deserialize<TestOrder>(_msgPackData, _msgPackOptions);
}