Skip to content

Add optional PerfLab counter regression thresholds - #5293

Draft
DrewScoggins wants to merge 4 commits into
dotnet:mainfrom
DrewScoggins:copilot/crank-perflab-harmonization
Draft

Add optional PerfLab counter regression thresholds#5293
DrewScoggins wants to merge 4 commits into
dotnet:mainfrom
DrewScoggins:copilot/crank-perflab-harmonization

Conversation

@DrewScoggins

@DrewScoggins DrewScoggins commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

  • add an optional per-counter regressionThreshold to the PerfLab Reporting contract
  • keep HigherIsBetter as the existing boolean direction field, with no additional direction enum or validation layer
  • migrate the Reporting project and tests from Newtonsoft.Json to System.Text.Json
  • provide Reporter.FromJson for contract round-tripping and preserve named floating-point literal handling
  • keep result-table output usable when counters or counter results are empty

Validation

  • 16 Reporting tests
  • Reporting package build

DrewScoggins and others added 2 commits August 19, 2026 11:44
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 26, 2026 16:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Reporting “PerfLab” JSON contract to support optional per-counter regression thresholds and to represent an explicitly unknown counter direction (while keeping legacy higherIsBetter compatibility), and adds stricter validation of test/counter invariants during serialization and reporting JSON generation.

Changes:

  • Added CounterDirection plus nullable RegressionThreshold, and introduced explicit handling for “unknown direction” via higherIsBetter: null.
  • Enforced counter/test validity (exactly one default counter; default must also be top; unique counter names; known direction and nonblank units for monitored counters) via validation hooks and Reporter.GetJson() validation.
  • Expanded unit tests to cover legacy JSON compatibility, new threshold serialization, unknown-direction behavior, and validation failures.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/tools/Reporting/Reporting/Test.cs Adds counter/test validation and runs it on serialize/deserialize; tightens default/top counter invariants.
src/tools/Reporting/Reporting/Reporter.cs Validates tests when constructing from JSON and before emitting JSON; improves result-table width handling when metric name can be null.
src/tools/Reporting/Reporting/Counter.cs Adds direction/threshold metadata and validation; preserves legacy JSON via higherIsBetter handling (including null for unknown).
src/tools/Reporting/Reporting.Tests/ReporterTests.cs Adds/updates tests for legacy compatibility, thresholds, unknown direction, and new validation rules.
Suppressed comments (2)

src/tools/Reporting/Reporting/Test.cs:34

  • The exception message includes an extra '$' before the counter name (it will render as a literal '$' in output). Remove the stray '$' so the message reports the actual name cleanly.

This issue also appears on line 65 of the same file.

        if (counter.DefaultCounter && Counters.Any(c => c.DefaultCounter))
        {
            throw new Exception($"Duplicate default counter, name: ${counter.Name}");
        }

src/tools/Reporting/Reporting/Test.cs:69

  • The duplicate-counter-name validation message includes an extra '$' before the name, which will show up as a literal '$' in logs/errors. Remove the stray '$'.
        var duplicateCounter = Counters.GroupBy(c => c.Name).FirstOrDefault(group => group.Count() > 1);
        if (duplicateCounter is not null)
        {
            throw new InvalidOperationException($"Duplicate counter name, name: ${duplicateCounter.Key}");
        }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/tools/Reporting/Reporting/Test.cs Outdated
Comment on lines +52 to +54
internal void Validate()
{
var defaultCounters = Counters.Where(c => c.DefaultCounter).ToList();
Keep HigherIsBetter as the existing boolean contract, retain only the optional per-counter regression threshold, and migrate Reporting JSON serialization to System.Text.Json.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 6f713269-e30d-4770-8a91-3fc53109abea
Copilot AI review requested due to automatic review settings August 31, 2026 17:40
@DrewScoggins DrewScoggins changed the title Add PerfLab counter threshold and direction metadata Add optional PerfLab counter regression thresholds Aug 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment on lines 18 to +24
public bool HigherIsBetter { get; set; }

public string MetricName { get; set; } = "Count";

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? RegressionThreshold { get; set; }


public IList<double>? Results { get; set; }

public override string ToString() => $"{nameof(Name)}: {Name}, {nameof(TopCounter)}: {TopCounter}, {nameof(DefaultCounter)}: {DefaultCounter}, {nameof(MetricName)}: {MetricName}";
Provide a System.Text.Json round-trip API and retain named floating-point literal handling for existing counter results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 6f713269-e30d-4770-8a91-3fc53109abea
Copilot AI review requested due to automatic review settings August 31, 2026 17:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants