60 lines
3.1 KiB
C#
60 lines
3.1 KiB
C#
using AyCode.Core.Serializers;
|
||
using AyCode.Core.Serializers.Binaries;
|
||
using AyCode.Core.Tests.TestModels;
|
||
|
||
namespace AyCode.Core.Benchmarks;
|
||
|
||
/// <summary>
|
||
/// Direct JIT-disassembly harness for the AcBinary <b>Large Serialize</b> hot path — the cell where
|
||
/// the PGO-driven inline bistability shows up (~120 µs/op fast mode ⇄ ~142 µs/op slow mode, same
|
||
/// source, run-to-run).
|
||
///
|
||
/// <para><b>Not a BenchmarkDotNet benchmark.</b> BDN's <c>DisassemblyDiagnoser</c> produced no output
|
||
/// ("No benchmarks were disassembled"); this harness leans on the runtime's own JIT disassembler
|
||
/// instead. <see cref="Run"/> builds the workload and exercises the Large Ser FastMode path — when the
|
||
/// process is launched with <c>DOTNET_JitDisasm=<pattern></c> the JIT dumps the x64 assembly of
|
||
/// every matching method to stdout as it compiles them.</para>
|
||
///
|
||
/// <para><b>Run it</b> (via the <c>--jitasm</c> switch). Set:</para>
|
||
/// <list type="bullet">
|
||
/// <item><c>DOTNET_TieredCompilation=0</c> — each method compiled once, straight to full-opt Tier-1:
|
||
/// deterministic codegen, no tiering/PGO lottery (so the disasm is reproducible).</item>
|
||
/// <item><c>DOTNET_JitDisasm=<pattern></c> — e.g. <c>*GeneratedWriter*</c> for the SGen writer
|
||
/// hot loop. The un-inlined <c>call</c>s in that loop are the candidates for the PGO-flipped inline
|
||
/// site; pinning the right callee with <c>[MethodImpl(AggressiveInlining)]</c> locks in the fast mode.</item>
|
||
/// </list>
|
||
///
|
||
/// <para>The workload mirrors <see cref="AcBinaryVsMemPackBenchmark"/> exactly — Large (5×5×5×10)
|
||
/// <see cref="TestOrder_All_False"/> graph, AsciiShort charset, FastMode + Compact wire.</para>
|
||
/// </summary>
|
||
public sealed class JitDisassemblyBenchmark
|
||
{
|
||
/// <summary>
|
||
/// Builds the Large workload and JITs + exercises the Large Ser FastMode hot path. With
|
||
/// <c>DOTNET_JitDisasm</c> set, the JIT emits the matching methods' disassembly to stdout on
|
||
/// first compile; the loop guarantees every reachable serializer method is JIT-compiled (and,
|
||
/// if tiering is left on, promoted to Tier-1).
|
||
/// </summary>
|
||
public void Run()
|
||
{
|
||
// Mirror AcBinaryVsMemPackBenchmark exactly: AsciiShort charset (where the Large-Ser bimodality
|
||
// was observed), Large (5×5×5×10) TestOrder_All_False graph, FastMode + Compact wire.
|
||
BenchmarkTestDataProvider.LongStringSuffix = CharsetSuffixes.AsciiShort;
|
||
|
||
var allTestData = BenchmarkTestDataProvider_All_False.CreateTestDataSets();
|
||
var largeSet = (TestDataSet<TestOrder_All_False>)allTestData.First(t => t.Name.StartsWith("Large"));
|
||
var order = largeSet.Order;
|
||
|
||
var options = AcBinarySerializerOptions.FastMode;
|
||
options.WireMode = WireMode.Compact;
|
||
|
||
Console.WriteLine("=== JIT-DISASM HARNESS: Large Ser FastMode (TestOrder_All_False, AsciiShort) — start ===");
|
||
|
||
byte[] last = null!;
|
||
for (var i = 0; i < 50; i++)
|
||
last = AcBinarySerializer.Serialize(order, options);
|
||
|
||
Console.WriteLine($"=== JIT-DISASM HARNESS: done — 50 Large Ser ops, last payload {last.Length} bytes ===");
|
||
}
|
||
}
|