AyCode.Core/AyCode.Core.Serializers.Con...
Loretta 8c20e23ea6 Add SGenOnly build config and centralize build settings
Introduced a new "SGenOnly" build configuration across the solution, updating Directory.Build.props, AyCode.Core.targets, and the .sln file for full support. Centralized TargetFramework and build properties in AyCode.Core.targets, removing redundancy from project files. Updated code to recognize SGEN_ONLY at compile time. Added new Bash commands for file conversion and cleanup. No functional code changes outside build and configuration logic.
2026-05-19 17:41:06 +02:00
..
AyCode.Core.Serializers.Console.csproj Add SGenOnly build config and centralize build settings 2026-05-19 17:41:06 +02:00
BenchmarkLoop.cs Refactor: BDN runner, unified reporting, doc overhaul 2026-05-15 20:54:42 +02:00
Configuration.cs Add SGenOnly build config and centralize build settings 2026-05-19 17:41:06 +02:00
Menu.cs Refactor charset profiles; split StringSmall decode paths 2026-05-19 12:58:22 +02:00
Program.cs Refactor: move benchmark engines to shared scenarios 2026-05-15 19:55:52 +02:00
README.md Refactor charset profiles; split StringSmall decode paths 2026-05-19 12:58:22 +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 (FixStrAscii vs StringSmall / Medium / Big / StringAscii), interning hit rates, and UTF-8 encode cost.

Consistent length across all charsets (UTF-16 char count): every *Short = 40 char, every *Long = 280 char (= Short × 7). Isolates the workload variable to UTF-8 byte content per charset (1-byte ASCII vs 2-byte Latin1 / Cyrillic vs 3-byte CJK vs mixed) — wire-size and encode/decode cost differences are pure charset effects, not length effects.

Profile UTF-16 char UTF-8 byte (approx) Tier
Latin1FixAscii 0 0 FixStrAscii / FixStr-equivalent (baseline-only)
AsciiShort 40 40 StringAscii (167)
AsciiLong 280 280 StringAscii (167)
Latin1Short 40 ~72 StringSmall (91)
Latin1Long (default) 280 ~504 StringMedium (94)
CjkBmpShort 40 ~104 StringSmall
CjkBmpLong 280 ~728 StringMedium
CyrillicShort 40 ~72 StringSmall
CyrillicLong 280 ~504 StringMedium
MixedShort 40 ~88 StringSmall
MixedLong 280 ~616 StringMedium

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.