using AyCode.Core.Tests.TestModels; using MemoryPack; using System.Buffers; using System.Runtime.CompilerServices; namespace AyCode.Core.Serializers.Console.Benchmarks; /// /// Benchmarks MemoryPack via the IBufferWriter overload with a pre-allocated, reused ArrayBufferWriter. /// Apples-to-apples counterpart to — MemoryPack's IBufferWriter /// is the path it's designed for. /// internal sealed class MemoryPackBufferWriterBenchmark : ISerializerBenchmark { private readonly TestOrder_All_True _order; private readonly MemoryPackSerializerOptions _options; private readonly byte[] _serialized; private readonly ArrayBufferWriter _bufferWriter; public BenchmarkEngine Engine => BenchmarkEngine.MemoryPack; public BenchmarkIoMode IoMode => BenchmarkIoMode.BufWrReuse; public BenchmarkDispatchMode DispatchMode => BenchmarkDispatchMode.SGen; // MemoryPack always uses [MemoryPackable] source-generated formatters public string OptionsPreset { get; } public int SerializedSize => _serialized.Length; public long SetupSerializeAllocBytes { get; } public long SetupDeserializeAllocBytes => 0; public string? OptionsDescription => $"StringEncoding={_options.StringEncoding}"; public MemoryPackBufferWriterBenchmark(TestOrder_All_True order, string optionsPreset) { _order = order; OptionsPreset = optionsPreset; _options = BenchmarkOptions.GetMemPack(); _serialized = MemoryPackSerializer.Serialize(order, _options); // Serialize-side setup only — see AcBinaryBufferWriterBenchmark for the full rationale. GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); var beforeSetup = GC.GetAllocatedBytesForCurrentThread(); _bufferWriter = new ArrayBufferWriter(_serialized.Length * 2); var afterSetup = GC.GetAllocatedBytesForCurrentThread(); SetupSerializeAllocBytes = afterSetup - beforeSetup; } [MethodImpl(MethodImplOptions.NoInlining)] public void Serialize() { _bufferWriter.ResetWrittenCount(); MemoryPackSerializer.Serialize(_bufferWriter, _order, _options); } // BufWr semantic: read from a ReadOnlySequence overload (apples-to-apples with AcBinary's // BufWr Deser path). MemoryPack's ROS overload also single-segment-fast-paths internally. [MethodImpl(MethodImplOptions.NoInlining)] public void Deserialize() => MemoryPackSerializer.Deserialize(new ReadOnlySequence(_serialized), _options); public bool VerifyRoundTrip() { _bufferWriter.ResetWrittenCount(); MemoryPackSerializer.Serialize(_bufferWriter, _order, _options); var roundTripped = MemoryPackSerializer.Deserialize(new ReadOnlySequence(_bufferWriter.WrittenMemory), _options); return BenchmarkLoop.DeepEqualsViaJson(_order, roundTripped); } }