87 lines
4.5 KiB
C#
87 lines
4.5 KiB
C#
using AyCode.Core.Benchmarks.Workloads.Scenarios;
|
|
using AyCode.Core.Serializers;
|
|
using AyCode.Core.Serializers.Binaries;
|
|
using AyCode.Core.Tests.TestModels;
|
|
using BenchmarkDotNet.Attributes;
|
|
|
|
namespace AyCode.Core.Benchmarks;
|
|
|
|
/// <summary>
|
|
/// BDN benchmark mirroring the Console app's "F" menu (<c>SerializerSelectionMode.FastestByte</c>) —
|
|
/// the focused 1:1 comparison between <b>AcBinary FastMode Byte[]</b> and <b>MemoryPack Default Byte[]</b>
|
|
/// across the 5 production-shaped test data cells (Small / Medium / Large / Repeated / Deep).
|
|
///
|
|
/// <para>Why this exists: the Console app's adaptive measurement engine gives fast turnaround but is
|
|
/// noise-prone; BDN's warmup + iteration + outlier-removal stack tightens the inter-engine delta to
|
|
/// the point where ~1-2% micro-optimizations become detectable. Both runners feed the SAME
|
|
/// <see cref="ISerializerBenchmark"/>-implementing workload (<see cref="AcBinaryBenchmark{T}"/> /
|
|
/// <see cref="MemoryPackBenchmark{T}"/>) — so the BDN numbers are directly comparable to Console's
|
|
/// <c>Console.FullBenchmark_Release_*.LLM</c> rows, only with tighter confidence intervals.</para>
|
|
///
|
|
/// <para>Output: BDN writes its native artifacts to <c>Test_Benchmark_Results/Benchmark/BDN/</c> (set
|
|
/// globally in <c>Program.cs</c> via <c>WithArtifactsPath</c>). <see cref="BdnSummaryAdapter"/> then
|
|
/// translates the <see cref="BenchmarkDotNet.Reports.Summary"/> into <see cref="Reporting.BenchmarkResult"/>
|
|
/// rows and emits the unified <c>Bdn.FullBenchmark_*.{log,LLM,output}</c> triplet next to Console's
|
|
/// counterparts in <c>Test_Benchmark_Results/Benchmark/</c>.</para>
|
|
/// </summary>
|
|
[MemoryDiagnoser]
|
|
public class AcBinaryVsMemPackBenchmark
|
|
{
|
|
/// <summary>
|
|
/// The 5 TestData cells matching Console's <c>BenchmarkLayer.Core</c> set —
|
|
/// Small (2x2x2x2) / Medium (3x3x3x4) / Large (5x5x5x10) / Repeated (10 items) / Deep (2x4x4x8).
|
|
/// Resolved at <see cref="GlobalSetup"/> time via <see cref="BenchmarkTestDataProvider_All_False.CreateTestDataSets"/>
|
|
/// (same provider Console uses) so the workload graphs are bit-for-bit identical.
|
|
/// </summary>
|
|
public static IEnumerable<string> TestDataNames => new[] { "Small", "Medium", "Large", "Repeated", "Deep" };
|
|
|
|
[ParamsSource(nameof(TestDataNames))]
|
|
public string TestData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Engine axis: AcBinary FastMode + Compact wire (UTF-8) vs MemoryPack Default (UTF-8). Compact-on-both-sides
|
|
/// keeps the string-encoding dimension constant so the comparison reflects engine differences only.
|
|
/// </summary>
|
|
[Params("AcBinary", "MemoryPack")]
|
|
public string Engine { get; set; } = "";
|
|
|
|
private ISerializerBenchmark _serializer = null!;
|
|
|
|
[GlobalSetup]
|
|
public void Setup()
|
|
{
|
|
// BDN runs each benchmark in an isolated child process — the parent's charset selection (a static
|
|
// field) does NOT cross the process boundary, so the child would otherwise fall back to the
|
|
// compile-time default (Latin1Long). Pin the BDN serializer benchmark to Latin1Short here so its
|
|
// cells line up with the Console Latin1Short runs. (Mirrored in BdnSummaryAdapter.WriteResults
|
|
// for the parent process — .LLM charset label + Size(B) column.)
|
|
BenchmarkTestDataProvider.LongStringSuffix = CharsetSuffixes.Latin1Short;
|
|
|
|
var allTestData = BenchmarkTestDataProvider_All_False.CreateTestDataSets();
|
|
var testDataSet = (TestDataSet<TestOrder_All_False>)allTestData.First(t => t.Name.StartsWith(TestData));
|
|
|
|
if (Engine == "AcBinary")
|
|
{
|
|
var options = AcBinarySerializerOptions.FastMode;
|
|
options.WireMode = WireMode.Compact;
|
|
_serializer = new AcBinaryBenchmark<TestOrder_All_False>(testDataSet.Order, options, "FastMode");
|
|
}
|
|
else
|
|
{
|
|
// MemoryPack's wire-mode-aligned ctor — Compact ↔ UTF-8 default for apples-to-apples vs AcBinary Compact.
|
|
_serializer = new MemoryPackBenchmark<TestOrder_All_False>(testDataSet.Order, WireMode.Compact, "Default");
|
|
}
|
|
|
|
// Round-trip correctness check before the BDN harness starts measuring — same gate the Console
|
|
// runner enforces. Fails the run early if anything's broken (rather than producing meaningless numbers).
|
|
if (!_serializer.VerifyRoundTrip())
|
|
throw new InvalidOperationException($"Round-trip verification FAILED for {Engine} on {TestData}.");
|
|
}
|
|
|
|
[Benchmark]
|
|
public void Serialize() => _serializer.Serialize();
|
|
|
|
[Benchmark]
|
|
public void Deserialize() => _serializer.Deserialize();
|
|
}
|