using AyCode.Core.Extensions;
using AyCode.Core.Tests.TestModels;
using BenchmarkDotNet.Attributes;
using Newtonsoft.Json;
using System.Text;
namespace AyCode.Core.Benchmarks;
///
/// Serialization benchmarks comparing AcJsonSerializer/Deserializer with Newtonsoft.Json.
/// Uses shared TestModels from AyCode.Core.Tests for consistency.
///
[MemoryDiagnoser]
public class SerializationBenchmarks
{
// Test data - uses shared TestModels
private TestOrder _testOrder = null!;
// Pre-serialized JSON for deserialization benchmarks
private string _newtonsoftJson = null!;
private string _ayCodeJson = null!;
// Target objects for Populate benchmarks
private TestOrder _populateTarget = null!;
// Settings
private JsonSerializerSettings _newtonsoftNoRefSettings = null!;
private JsonSerializerSettings _ayCodeSettings = null!;
[GlobalSetup]
public void Setup()
{
// Newtonsoft WITHOUT reference handling (baseline)
_newtonsoftNoRefSettings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.None
};
// AyCode WITH reference handling
_ayCodeSettings = SerializeObjectExtensions.Options;
// Create benchmark data using shared factory
// ~1500 objects: 5 items × 4 pallets × 3 measurements × 5 points = 300 points + containers
_testOrder = TestDataFactory.CreateBenchmarkOrder(
itemCount: 5,
palletsPerItem: 4,
measurementsPerPallet: 3,
pointsPerMeasurement: 5);
// Pre-serialize for deserialization benchmarks
_newtonsoftJson = JsonConvert.SerializeObject(_testOrder, _newtonsoftNoRefSettings);
_ayCodeJson = _testOrder.ToJson(_ayCodeSettings);
// Create target for populate benchmarks
_populateTarget = new TestOrder();
// Output sizes for comparison
var newtonsoftBytes = Encoding.UTF8.GetByteCount(_newtonsoftJson);
var ayCodeBytes = Encoding.UTF8.GetByteCount(_ayCodeJson);
Console.WriteLine("=== JSON Size Comparison ===");
Console.WriteLine($"Newtonsoft (skip defaults): {_newtonsoftJson.Length:N0} chars ({newtonsoftBytes:N0} bytes)");
Console.WriteLine($"AyCode (refs+skip): {_ayCodeJson.Length:N0} chars ({ayCodeBytes:N0} bytes)");
Console.WriteLine($"Size reduction: {(1.0 - (double)ayCodeBytes / newtonsoftBytes) * 100:F1}%");
}
#region Serialization Benchmarks
[Benchmark(Description = "Newtonsoft (no refs)")]
[BenchmarkCategory("Serialize")]
public string Serialize_Newtonsoft_NoRefs()
=> JsonConvert.SerializeObject(_testOrder, _newtonsoftNoRefSettings);
[Benchmark(Description = "AyCode (with refs)")]
[BenchmarkCategory("Serialize")]
public string Serialize_AyCode_WithRefs()
=> _testOrder.ToJson(_ayCodeSettings);
[Benchmark(Description = "AcJsonSerializer (custom)")]
[BenchmarkCategory("Serialize")]
public string Serialize_AcJsonSerializer()
=> AcJsonSerializer.Serialize(_testOrder);
#endregion
#region Deserialization Benchmarks
[Benchmark(Description = "Newtonsoft (no refs)")]
[BenchmarkCategory("Deserialize")]
public TestOrder? Deserialize_Newtonsoft_NoRefs()
=> JsonConvert.DeserializeObject(_newtonsoftJson, _newtonsoftNoRefSettings);
[Benchmark(Description = "AyCode (with refs)")]
[BenchmarkCategory("Deserialize")]
public TestOrder? Deserialize_AyCode_WithRefs()
=> _ayCodeJson.JsonTo(_ayCodeSettings);
[Benchmark(Description = "AcJsonDeserializer (custom)")]
[BenchmarkCategory("Deserialize")]
public TestOrder? Deserialize_AcJsonDeserializer()
=> AcJsonDeserializer.Deserialize(_ayCodeJson);
#endregion
#region Populate Benchmarks
[Benchmark(Description = "AcJsonDeserializer.Populate")]
[BenchmarkCategory("Populate")]
public void Populate_AcJsonDeserializer()
{
// Create fresh target for each iteration to avoid state pollution
var target = new TestOrder();
AcJsonDeserializer.Populate(_ayCodeJson, target);
}
[Benchmark(Description = "Newtonsoft PopulateObject")]
[BenchmarkCategory("Populate")]
public void Populate_Newtonsoft()
{
// Create fresh target for each iteration to match the other benchmark
var target = new TestOrder();
JsonConvert.PopulateObject(_newtonsoftJson, target, _newtonsoftNoRefSettings);
}
#endregion
#region JSON Size Comparison
[Benchmark(Description = "JSON Size - Newtonsoft")]
[BenchmarkCategory("Size")]
public int JsonSize_Newtonsoft() => _newtonsoftJson.Length;
[Benchmark(Description = "JSON Size - AyCode")]
[BenchmarkCategory("Size")]
public int JsonSize_AyCode() => _ayCodeJson.Length;
#endregion
}