using AyCode.Core.Serializers.Binaries; using MemoryPack; namespace AyCode.Core.Serializers.Console.Benchmarks; /// /// Per-engine options-formatting + selection helpers shared by all benchmark rows. Centralizes /// the Options-column display string (so the .log / .LLM / console headers stay consistent) and /// the MemoryPack WireMode-aligned options selection (so AcBinary FastWire ↔ MemoryPack /// UTF-16 comparisons stay apples-to-apples). /// internal static class BenchmarkOptions { /// /// Common Options-column formatter for every AcBinary serializer benchmark row. Renders the /// configured options-level value AND the effective attribute-level enable flag side-by-side /// (e.g. Interning=All(opt) | False (attr)) so attribute-suppressed features cannot /// silently mislead. Pass any benchmark-specific extras (e.g. ", BufferSize=4096B") /// in — they are appended after the common fields. /// internal static string BuildAcBinary(AcBinarySerializerOptions options, string extra = "") { // PropertyFilter: opt-side is "Set"/"None" depending on whether a callback is registered (the callback // itself isn't a meaningful display value); attr-side is the cross-type-aggregated bool (true = every // tagged type has the feature enabled, false = at least one type opted out via // [AcBinarySerializable(enablePropertyFilterFeature: false)] → SGen-emit + Runtime hot-loop both gate). var propFilterOpt = options.PropertyFilter == null ? "None" : "Set"; return $"WireMode={options.WireMode}, " + $"RefHandling={options.ReferenceHandling}(opt) | {Configuration.AttrFlags.refHandling} (attr), " + $"Interning={options.UseStringInterning}(opt) | {Configuration.AttrFlags.internString} (attr), " + $"Metadata={options.UseMetadata}(opt) | {Configuration.AttrFlags.metadata} (attr), " + $"PropertyFilter={propFilterOpt}(opt) | {Configuration.AttrFlags.propertyFilter} (attr), " + $"SGen={options.UseGeneratedCode}, " + $"Compression={options.UseCompression}{extra}"; } /// /// Returns MemoryPack serializer options aligned with for a fair /// apples-to-apples wire-format comparison: /// /// (UTF-8) — both /// engines encode UTF-8, comparison is purely about header / tier / dispatch overhead. /// (UTF-16 raw memcpy) — /// both engines write UTF-16 raw bytes, so wire-size and CPU comparison reflect the same string-encoding family. /// /// Without this alignment the FastWire vs MemPack-default comparison conflates two unrelated dimensions /// (UTF-16 raw vs UTF-8 encoded) and produces a misleading +40% wire-size delta that is structurally /// the encoding-family difference, NOT an AcBinary-specific overhead. /// internal static MemoryPackSerializerOptions GetMemPack() => Configuration.SelectedWireMode == WireMode.Fast ? MemoryPackSerializerOptions.Utf16 : MemoryPackSerializerOptions.Default; }