196 lines
7.6 KiB
C#
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);
|
|
} |