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=&lt;pattern&gt;</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=&lt;pattern&gt;</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 ===");
    }
}
