AyCode.Core/AyCode.Core.Serializers.Con...
Loretta c611d4b535 Refactor: BDN runner, unified reporting, doc overhaul
- Introduce BDN-based runner (AcBinaryVsMemPackBenchmark) mirroring Console's FastestByte scenario; add BdnSummaryAdapter for unified result translation.
- Standardize output: both runners emit .log/.LLM/.output triplets; BDN-native artifacts go under Benchmark/BDN/.
- Simplify CLI: replace granular switches with --serializers; update help and usage.
- Remove legacy benchmark classes; focus on scenario-based approach.
- Rewrite README.md for both AyCode.Benchmark and Console to document dual-runner architecture, output conventions, and dependencies.
- Rotate BINARY_TODO.md; archive closed entries to BINARY_TODO_2026_04.md and BINARY_TODO_2026_05.md.
- Add BINARY_SGEN_OPTIMIZATION.md for SGen per-property emit optimization notes.
- Update comments and docstrings for clarity and maintainability; clarify BenchmarkResult iteration semantics for BDN rows.
2026-05-15 20:54:42 +02:00
..
AyCode.Core.Serializers.Console.csproj Refactor: move benchmark engines to shared scenarios 2026-05-15 19:55:52 +02:00
BenchmarkLoop.cs Refactor: BDN runner, unified reporting, doc overhaul 2026-05-15 20:54:42 +02:00
Configuration.cs Refactor: BDN runner, unified reporting, doc overhaul 2026-05-15 20:54:42 +02:00
Menu.cs Refactor: move benchmark engines to shared scenarios 2026-05-15 19:55:52 +02:00
Program.cs Refactor: move benchmark engines to shared scenarios 2026-05-15 19:55:52 +02:00
README.md Refactor: BDN runner, unified reporting, doc overhaul 2026-05-15 20:54:42 +02:00

README.md

AyCode.Core.Serializers.Console

Interactive console runner for the serializer benchmark suite. Targets .NET 9.

Companion: shares its workload + reporting infrastructure with the BDN runner in AyCode.Benchmark/ via <ProjectReference>. See that project's README for the full dual-runner architecture.

Role

This is the fast-iteration half of the benchmark stack — a custom adaptive measure engine optimized for short turnaround (~1-3 min full run) during micro-optimization loops. The BDN half lives in AyCode.Benchmark and produces statistically tighter numbers (~5-15 min full run) for before-commit validation. Both runners emit the same .log / .LLM / .output triplet to Test_Benchmark_Results/Benchmark/ — Console prefixes with Console., BDN with Bdn..

Compared serializers

  • AcBinary — multiple options presets: FastMode (Compact wire, no ref handling, no interning), Default (with ref handling + interning), plus SGen / Runtime dispatch variants and Compact / Fast wire modes.
  • MemoryPack — SOTA baseline, wire-mode-aligned with AcBinary for apples-to-apples encoding comparison (UTF-8 ↔ Compact, UTF-16 ↔ Fast).
  • MessagePack — JIT-only (AOT incompatible due to dynamic resolver).
  • System.Text.Json — reference comparison (commented out in CreateSerializers by default).

Key files

  • Program.cs — entry point. Parses CLI args (Core / Comprehensive / Edge / per-cell / op-mode / serializer-set) or falls into interactive Menu.
  • Menu.cs — interactive layer/serializer-set selection + nested settings (iteration counts, wire mode, charset).
  • BenchmarkLoop.cs — custom adaptive measure engine. CPU 0 affinity pin + High priority for stabilization, JIT pre-warmup, phase-isolated Ser/Des warmup→measure with GC.Collect at every boundary, 10-sample median + pilot discard, adaptive iter calibration to ~250ms/cell wall-clock, dedicated allocation-only sample.
  • Configuration.cs — Console-side state (SelectedWireMode, WarmupIterations, BenchmarkSamples, TargetSampleMs, charset selection, BuildConfiguration const from #if DEBUG/RELEASE/AYCODE_NATIVEAOT).

Workload + reporting types — ISerializerBenchmark, BenchmarkResult, BenchmarkOptions, BenchmarkEnums, BenchmarkReportWriter, ReportingContext, the 12 concrete *Benchmark<T> classes (AcBinaryBenchmark, MemoryPackBenchmark, AcBinaryBufferWriterBenchmark, ...), RoundTripValidator — live in AyCode.Benchmark/Workloads/Scenarios/ and AyCode.Benchmark/Reporting/.

Test data

5 cells, provided by AyCode.Core.Tests.TestModels.BenchmarkTestDataProvider*:

  • Small (2×2×2×2)
  • Medium (3×3×3×4)
  • Large (5×5×5×10)
  • Repeated Strings (10 items, string-deduplication stress)
  • Deep Nested (2×4×4×8, depth stress)

20% IId reference rate by default. Two graph variants (TestOrder_All_False / _All_True) are built per cell — AcBinary's option preset picks which variant gets fed to it (UsesAllFalseVariant rule in BenchmarkLoop).

Charset profiles (Menu → Settings → Charset)

Controls the BenchmarkTestDataProvider.LongStringSuffix — the string-tail appended to property values. Influences string-marker selection on the wire (FixStr vs StringSmall / Medium / Big), interning hit rates, and UTF-8 encode cost.

Profile Content
Latin1FixAscii Empty suffix (short FixStr fast-path stress)
Latin1Short "árvíztűrő tükörfúrógép" (~24 char Hungarian mixed)
Latin1Long ~47-char Latin1 mixed (default)
CjkBmp CJK BMP (3-byte UTF-8 runs)
Cyrillic Russian Cyrillic (2-byte UTF-8 runs)
Mixed Hungarian + CJK + Cyrillic + emoji (full-spectrum + surrogate pairs)

CLI

dotnet run -c Release --project AyCode.Core.Serializers.Console -- [arg]
Arg Result
(no args) Interactive menu — pick layer (Core / Comprehensive / Edge / Small / Medium / Large / Repeated / Deep / All) × serializer-set (Standard / FastestByte ["F"] / AsyncPipe ["P"]).
Core / Comprehensive / Edge / Small / Medium / Large / Repeated / Deep / All Run that layer at Standard serializer-set, All op-mode.
FastestByte / AsyncPipe / Standard Run that serializer-set, All layer, All op-mode.
Serialize / Deserialize / All Run that op-mode, All layer, Standard serializer-set.
quick Single-sample fast mode (Debug-equivalent — very loose numbers, smoke-test only).

Output: Test_Benchmark_Results/Benchmark/Console.FullBenchmark_<Build>_<timestamp>.{log,LLM,output}.

Dependencies

Dependency Purpose
AyCode.Core (ProjectReference) AcBinary serializer
AyCode.Core.Tests (ProjectReference) Test data factory + test models
AyCode.Benchmark (ProjectReference) Shared workload + reporting (ISerializerBenchmark, BenchmarkResult, BenchmarkReportWriter, ReportingContext, the 12 concrete benchmark classes)
MemoryPack Comparison target (also via Workloads)
MessagePack Comparison target
Newtonsoft.Json Comparison target (currently disabled)

Build & publish notes

  • <StartupObject>AyCode.Core.Serializers.Console.Program</StartupObject> in the csproj explicitly disambiguates the entry point — necessary because this Exe references another Exe (AyCode.Benchmark), and the build would otherwise complain about multiple Main methods.
  • AOT publish (dotnet publish -c Release) is configured via '$(_IsPublishing)' == 'true' PropertyGroup. The Benchmark project's BDN-stack (BenchmarkDotNet, Iced disassembler, MongoDB.Bson) is pulled in transitively — accepted tradeoff for the unified workload sharing.