56 lines
3.4 KiB
C#
56 lines
3.4 KiB
C#
using AyCode.Core.Serializers.Binaries;
|
|
using MemoryPack;
|
|
|
|
namespace AyCode.Core.Serializers.Console.Benchmarks;
|
|
|
|
/// <summary>
|
|
/// 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 <c>WireMode</c>-aligned options selection (so AcBinary FastWire ↔ MemoryPack
|
|
/// UTF-16 comparisons stay apples-to-apples).
|
|
/// </summary>
|
|
internal static class BenchmarkOptions
|
|
{
|
|
/// <summary>
|
|
/// 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. <c>Interning=All(opt) | False (attr)</c>) so attribute-suppressed features cannot
|
|
/// silently mislead. Pass any benchmark-specific extras (e.g. <c>", BufferSize=4096B"</c>)
|
|
/// in <paramref name="extra"/> — they are appended after the common fields.
|
|
/// </summary>
|
|
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}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns MemoryPack serializer options aligned with <see cref="Configuration.SelectedWireMode"/> for a fair
|
|
/// apples-to-apples wire-format comparison:
|
|
/// <list type="bullet">
|
|
/// <item><see cref="WireMode.Compact"/> → <see cref="MemoryPackSerializerOptions.Default"/> (UTF-8) — both
|
|
/// engines encode UTF-8, comparison is purely about header / tier / dispatch overhead.</item>
|
|
/// <item><see cref="WireMode.Fast"/> → <see cref="MemoryPackSerializerOptions.Utf16"/> (UTF-16 raw memcpy) —
|
|
/// both engines write UTF-16 raw bytes, so wire-size and CPU comparison reflect the same string-encoding family.</item>
|
|
/// </list>
|
|
/// 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.
|
|
/// </summary>
|
|
internal static MemoryPackSerializerOptions GetMemPack() =>
|
|
Configuration.SelectedWireMode == WireMode.Fast
|
|
? MemoryPackSerializerOptions.Utf16
|
|
: MemoryPackSerializerOptions.Default;
|
|
}
|