92 lines
3.2 KiB
C#
92 lines
3.2 KiB
C#
using AyCode.Core.Serializers.Binaries;
|
|
using AyCode.Core.Tests.TestModels;
|
|
using BenchmarkDotNet.Attributes;
|
|
using BenchmarkDotNet.Diagnosers;
|
|
using BenchmarkDotNet.Jobs;
|
|
|
|
namespace AyCode.Core.Benchmarks;
|
|
|
|
/// <summary>
|
|
/// 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)
|
|
/// </summary>
|
|
[SimpleJob(RuntimeMoniker.Net90)]
|
|
[DisassemblyDiagnoser(maxDepth: 4, printSource: true, exportGithubMarkdown: true)]
|
|
[MemoryDiagnoser(displayGenColumns: false)]
|
|
public class JitDisassemblyBenchmark
|
|
{
|
|
private TestOrder_All_True _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_All_True");
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// FastMode serialize — no ref tracking, no string interning.
|
|
/// </summary>
|
|
[Benchmark(Baseline = true)]
|
|
public byte[] Serialize_FastMode()
|
|
{
|
|
return AcBinarySerializer.Serialize(_order, _fastModeOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// FastMode deserialize.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public TestOrder_All_True Deserialize_FastMode()
|
|
{
|
|
return AcBinaryDeserializer.Deserialize<TestOrder_All_True>(_serializedFastMode, _fastModeOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Default serialize — ref tracking + string interning (scan pass + write pass).
|
|
/// Shows IdentityMap lookup overhead in hot path.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public byte[] Serialize_Default()
|
|
{
|
|
return AcBinarySerializer.Serialize(_order, _defaultOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Default deserialize — ref tracking + string interning.
|
|
/// </summary>
|
|
[Benchmark]
|
|
public TestOrder_All_True Deserialize_Default()
|
|
{
|
|
return AcBinaryDeserializer.Deserialize<TestOrder_All_True>(_serializedDefault, _defaultOptions);
|
|
}
|
|
}
|