using AyCode.Core.Serializers.Console.Benchmarks; namespace AyCode.Core.Serializers.Console; /// /// Per-cell benchmark result row. Populated by the benchmark execution loop in /// BenchmarkLoop.RunBenchmarksForTestData; consumed by the output formatters in /// Output (console table + .log + .LLM file writers). Pure DTO — no behaviour. /// internal sealed class BenchmarkResult { public string TestDataName { get; set; } = ""; public BenchmarkEngine Engine { get; set; } public BenchmarkIoMode IoMode { get; set; } public BenchmarkDispatchMode DispatchMode { get; set; } public string OptionsPreset { get; set; } = ""; /// True if Serialize() captures a full round-trip and Deserialize() is a no-op /// (single-use streaming transports like NamedPipe). Excluded from "Fastest Serialize" / "Fastest Deserialize" /// winners rankings; still ranked in "Fastest Round-trip". Display-side: Ser µs/op / SerAlloc / Des µs/op / DesAlloc /// all show "N/A" since they were never measured separately; RT µs/op / RT Alloc carry the full round-trip values. public bool IsRoundTripOnly { get; set; } /// Synthesized display name for backwards compatibility / single-string-row scenarios. Includes DispatchMode so SGen and Runtime variants of the same preset don't collide in grouping (e.g. SUMMARY: WINNERS). public string SerializerName => $"{Engine.ToDisplay()} ({IoMode.ToDisplay()}, {OptionsPreset}, {DispatchMode.ToDisplay()})"; public string? OptionsDescription { get; set; } public int SerializedSize { get; set; } public double SerializeTimeMs { get; set; } public double DeserializeTimeMs { get; set; } // Per-sample min/max alongside the median (median is the *Time*Ms field above). Surfaces // inter-sample range — the visible noise floor for the row. 0 when the operation was skipped // (mode != "all"/"ser"/"des") or when a single-sample fast path was used (min == max == median). public double SerializeTimeMinMs { get; set; } public double SerializeTimeMaxMs { get; set; } public double DeserializeTimeMinMs { get; set; } public double DeserializeTimeMaxMs { get; set; } // Sample-population stddev (ms). Used by FormatMicrosWithRange to compute CV (stddev/mean) // and emit the ⚠️ marker on rows above Configuration.UnstableCVThreshold. 0 in single-sample mode. public double SerializeTimeStdDevMs { get; set; } public double DeserializeTimeStdDevMs { get; set; } // Per-row adaptive iteration count (post-CalibrateIterations). Each Ser and Des function calibrates // independently to land its sample window at ~Configuration.TargetSampleMs; per-op µs is then iter-independent // (`SerializeTimeMs / SerializeIterations * 1000`). For round-trip-only rows (NamedPipe etc.), // RoundTripIterations carries the calibrated iter count; SerializeIterations and DeserializeIterations // stay 0 (Ser and Des are not separately measurable on those rows). public int SerializeIterations { get; set; } public int DeserializeIterations { get; set; } public int RoundTripIterations { get; set; } public long SerializeAllocBytesPerOp { get; set; } public long DeserializeAllocBytesPerOp { get; set; } public long SetupSerializeAllocBytes { get; set; } public long SetupDeserializeAllocBytes { get; set; } /// Total round-trip time. For in-memory benchmarks: synthesized so that /// RoundTripTimeMs / RoundTripIterations yields the correct SerPerOp + DesPerOp µs/op /// (necessary because Ser and Des may have different iter counts post-calibration). /// For round-trip-only benchmarks (NamedPipe etc.): the directly-measured pipe round-trip time. public double RoundTripTimeMs { get; set; } // Round-trip min/max + stddev — only populated for round-trip-only benchmarks (NamedPipe etc.) where // RT is directly measured. For in-memory rows RT = Ser + Des, which has no single-sample // distribution; surface Ser/Des range separately instead. public double RoundTripTimeMinMs { get; set; } public double RoundTripTimeMaxMs { get; set; } public double RoundTripTimeStdDevMs { get; set; } /// Total round-trip allocation per op. For in-memory benchmarks: SerializeAlloc + DeserializeAlloc. /// For round-trip-only benchmarks: process-wide allocation measured via /// (covers ALL threads — client, server-drain, channel internals — not just the caller). public long RoundTripAllocBytesPerOp { get; set; } }