using AyCode.Core.Serializers.Binaries; using AyCode.Core.Tests.TestModels; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Jobs; namespace AyCode.Core.Benchmarks; /// /// JIT disassembly benchmark for AcBinarySerializer hot path analysis. /// Shows actual x64 assembly generated by the JIT to verify inlining decisions. /// /// Usage: dotnet run -c Release -- --filter *JitDisassemblyBenchmark* /// Or from Program.cs: --jitasm /// /// Output: BenchmarkDotNet artifacts folder contains .asm files with full disassembly. /// Look for: /// - WritePropertyOrSkip / WritePropertyMarkerless: are they inlined or called? /// - WriteInt32 / WriteFloat64Unsafe / etc.: inlined into the caller or separate calls? /// - context parameter passing: register usage (RCX/RDX/R8/R9) /// [SimpleJob(RuntimeMoniker.Net90)] [DisassemblyDiagnoser(maxDepth: 4, printSource: true, exportGithubMarkdown: true)] [MemoryDiagnoser(displayGenColumns: false)] public class JitDisassemblyBenchmark { private TestOrder _order = null!; private AcBinarySerializerOptions _fastModeOptions = null!; private AcBinarySerializerOptions _defaultOptions = null!; private byte[] _serializedFastMode = null!; private byte[] _serializedDefault = null!; [GlobalSetup] public void Setup() { TestDataFactory.ResetIdCounter(); var sharedTag = TestDataFactory.CreateTag("SharedTag"); var sharedUser = TestDataFactory.CreateUser("shareduser"); // Medium data: enough properties to show loop behavior, not too large for disassembly _order = TestDataFactory.CreateOrder( itemCount: 3, palletsPerItem: 3, measurementsPerPallet: 3, pointsPerMeasurement: 4, sharedTag: sharedTag, sharedUser: sharedUser); _fastModeOptions = AcBinarySerializerOptions.FastMode; _defaultOptions = AcBinarySerializerOptions.Default; _serializedFastMode = AcBinarySerializer.Serialize(_order, _fastModeOptions); _serializedDefault = AcBinarySerializer.Serialize(_order, _defaultOptions); } /// /// FastMode serialize — no ref tracking, no string interning. /// [Benchmark(Baseline = true)] public byte[] Serialize_FastMode() { return AcBinarySerializer.Serialize(_order, _fastModeOptions); } /// /// FastMode deserialize. /// [Benchmark] public TestOrder Deserialize_FastMode() { return AcBinaryDeserializer.Deserialize(_serializedFastMode, _fastModeOptions); } /// /// Default serialize — ref tracking + string interning (scan pass + write pass). /// Shows IdentityMap lookup overhead in hot path. /// [Benchmark] public byte[] Serialize_Default() { return AcBinarySerializer.Serialize(_order, _defaultOptions); } /// /// Default deserialize — ref tracking + string interning. /// [Benchmark] public TestOrder Deserialize_Default() { return AcBinaryDeserializer.Deserialize(_serializedDefault, _defaultOptions); } }