using StellaOps.Bench.ScannerAnalyzers.Baseline; namespace StellaOps.Bench.ScannerAnalyzers.Reporting; internal sealed class BenchmarkScenarioReport { private const double RegressionLimitDefault = 1.2d; public BenchmarkScenarioReport(ScenarioResult result, BaselineEntry? baseline, double? regressionLimit = null) { Result = result ?? throw new ArgumentNullException(nameof(result)); Baseline = baseline; RegressionLimit = regressionLimit is { } limit && limit > 0 ? limit : RegressionLimitDefault; MaxRegressionRatio = CalculateRatio(result.MaxMs, baseline?.MaxMs); MeanRegressionRatio = CalculateRatio(result.MeanMs, baseline?.MeanMs); } public ScenarioResult Result { get; } public BaselineEntry? Baseline { get; } public double RegressionLimit { get; } public double? MaxRegressionRatio { get; } public double? MeanRegressionRatio { get; } public bool RegressionBreached => MaxRegressionRatio.HasValue && MaxRegressionRatio.Value >= RegressionLimit; public string? BuildRegressionFailureMessage() { if (!RegressionBreached || MaxRegressionRatio is null) { return null; } var percentage = (MaxRegressionRatio.Value - 1d) * 100d; return $"{Result.Id} exceeded regression budget: max {Result.MaxMs:F2} ms vs baseline {Baseline!.MaxMs:F2} ms (+{percentage:F1}%)"; } private static double? CalculateRatio(double current, double? baseline) { if (!baseline.HasValue) { return null; } if (baseline.Value <= 0d) { return null; } return current / baseline.Value; } }