Skip to content

Benchmark external specs (azure-rest-api-specs) with a separate dashboard#4862

Merged
tadelesh merged 5 commits into
mainfrom
benchmark
Jul 14, 2026
Merged

Benchmark external specs (azure-rest-api-specs) with a separate dashboard#4862
tadelesh merged 5 commits into
mainfrom
benchmark

Conversation

@tadelesh

@tadelesh tadelesh commented Jul 10, 2026

Copy link
Copy Markdown
Member

Implements external-spec benchmarking, designed in #4801.

What this adds

Benchmark real specs from another repository (e.g. azure-rest-api-specs) as a separate, opt-in group alongside the built-in specs, with their own dashboard view — kept out of the main baseline.

Runner (generic)

A benchmark spec is anything the runner can compile: a local spec (a directory with main.tsp) or an external spec (a directory with spec.json). --specs-dir selects which set to run; both are treated uniformly and produce one results file. There is no built-in/external split in the tool itself — the distinction is made by CI (which directory to run) and the dashboard (which dataset to show).

External specs are sparse-checked-out into packages/benchmark/.external/ (git-ignored) and compiled against this workspace's packages, so results reflect local library changes (TCGC, client emitters, linters). ref tracks latest (no pinning). Each external spec directory carries a tspconfig.yaml (copied into the checkout) that selects the emitters and linter measured — e.g. TCGC + the ARM ruleset — exactly like a local spec.

Storage

store-results --results-dir <dir> stores each group under its own directory on benchmark-data (results/ for the baseline, external-results/ for external). The push rebases-and-retries so the two workflows writing the branch concurrently don't fail.

Dashboard

The benchmarks page gains a Main baseline / External specs switch. The External view reads external-results/history.json and shows a single chart switchable between two modes:

  • By emitter (cross-spec) — one line per spec for a chosen emitter.
  • By spec (cross-emitter) — one line per emitter for a chosen spec.

PR comments

The external group posts its own sticky PR comment ("⚡ External Spec Benchmark Results"), separate from the main one, comparing against the external-results rolling baseline.

Workflows (reusable)

benchmark-run.yml and benchmark-comment-run.yml are reusable templates holding the run/comment logic. benchmark.yml (main) and benchmark-external.yml instantiate the run template with their own parameters; benchmark-comment.yml and benchmark-comment-external.yml instantiate the comment template. Adding a group is a small instance file, not duplicated logic.

Included external specs

compute, web (AppService), and network — large ARM specs from azure-rest-api-specs, measuring TCGC + the ARM ruleset.

Notes

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

⚡ Benchmark Results

⚠️ 1 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 30.4ms 🔴 32.2ms +6.2% 🔴
Full details – comparing c90de43 vs baseline rolling-baseline-f49cd9d-f3a0f6d (rolling baseline (20 main runs))
Metric Baseline Current Change
total 🔴 1.03s 🔴 1.06s +3.8%
loader 🟡 310.9ms 🟡 326.2ms +4.9%
resolver 🟢 40.5ms 🟢 41.2ms +1.9%
checker 🟡 369.3ms 🟡 383.6ms +3.9%
validation 🟢 85.6ms 🟢 87.6ms +2.3%
 ↳ validation/@azure-tools/typespec-azure-core 🟡 12.8ms 🟡 13.4ms +4.8%
 ↳ validation/@typespec/http 🟡 15.7ms 🟡 16.3ms +3.7%
 ↳ validation/@typespec/rest 🟢 1.6ms 🟢 1.7ms +3.5%
 ↳ validation/@typespec/versioning 🔴 51.5ms 🔴 52.1ms +1.3%
 ↳ validation/compiler 🟢 3.9ms 🟢 4.0ms +2.7%
linter 🟡 218.5ms 🟡 225.4ms +3.2%
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.1ms 🟢 0.1ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.6ms 🟢 0.6ms -1.2%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 8.5ms 🟢 8.7ms +3.1%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 1.5ms 🟢 1.5ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.2ms 🟢 0.2ms +0.1%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 2.0ms 🟢 2.0ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 1.4ms 🟢 1.4ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.4ms 🟢 0.4ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.5ms 🟢 0.5ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.8ms 🟢 0.8ms +0.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.7ms 🟢 0.7ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 1.0ms 🟢 1.0ms -0.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.2ms 🟢 0.2ms +0.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.3ms 🟢 0.3ms +1.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.2ms 🟢 0.2ms +2.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.8ms 🟢 0.8ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.8ms 🟢 0.9ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 27.2ms 🔴 28.5ms +4.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 2.1ms 🟢 2.1ms +1.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.2ms 🟢 0.3ms +6.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.4ms 🟢 0.4ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 2.0ms 🟢 2.0ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 2.3ms 🟢 2.3ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 3.2ms 🟢 3.3ms +1.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 28.3ms 🔴 29.5ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 33.9ms 🔴 35.1ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.1ms 🟢 0.1ms +9.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 7.8ms 🟢 8.2ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.4ms 🟢 0.4ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.1ms 🟢 0.2ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.4ms 🟢 0.4ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.8ms 🟢 0.8ms +0.4%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.4ms 🟢 0.4ms -1.3%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.5ms 🟢 0.5ms +0.3%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.1ms 🟢 0.1ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 33.2ms 🔴 34.6ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.7ms 🟢 0.7ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.5ms 🟢 0.5ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 7.7ms 🟢 8.0ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.3ms 🟢 0.3ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🔴 21.7ms 🔴 21.7ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.3ms 🟢 0.3ms -2.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟡 12.3ms 🟡 12.5ms +1.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.2ms 🟢 0.2ms +0.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 5.0ms 🟢 4.5ms -10.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟡 17.2ms 🟡 17.5ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.6ms 🟢 0.7ms +4.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 1.4ms 🟢 1.4ms +4.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.2ms 🟢 0.2ms -4.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.5ms 🟢 0.5ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.4ms 🟢 0.4ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.1ms 🟢 0.1ms -0.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.2ms 🟢 0.2ms +5.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.3ms 🟢 0.3ms +0.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.2ms 🟢 0.2ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.5ms 🟢 0.5ms +3.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.1ms 🟢 0.1ms -1.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.6ms 🟢 0.6ms +3.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 9.1ms 🟢 9.5ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.8ms 🟢 0.9ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.4ms 🟢 0.4ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.4ms 🟢 0.4ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.2ms 🟢 0.2ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.4ms 🟢 0.4ms -3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.1ms 🟢 0.1ms +7.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🔴 20.0ms 🔴 20.9ms +4.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.1ms 🟢 0.2ms +6.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 1.0ms 🟢 1.0ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.3ms 🟢 0.3ms +3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.3ms 🟢 0.3ms +3.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-reserved-resource-property 🟢 0.2ms 🟢 0.2ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.5ms 🟢 0.5ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 30.4ms 🔴 32.2ms +6.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.4ms 🟢 0.4ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.4ms 🟢 0.4ms +0.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 5.4ms 🟢 5.5ms +1.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.7ms 🟢 0.7ms -1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.3ms 🟢 0.3ms +2.3%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 2.3ms 🟢 2.4ms +1.8%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 1.7ms 🟢 1.7ms +1.9%
emit 🔴 6.13s 🔴 6.28s +2.4%
 ↳ emit/@Azure-Tools 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@azure-tools/typespec-autorest 🟢 127.0ms 🟢 129.7ms +2.2%
 ↳ emit/@azure-tools/typespec-python 🔴 2.28s 🔴 2.34s +2.6%
 ↳ emit/@typespec 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@typespec/http-client-js 🔴 578.5ms 🔴 590.3ms +2.0%
 ↳ emit/@typespec/openapi3 🟢 109.5ms 🟢 112.2ms +2.5%
 ↳ emit/@typespec/openapi3/compute 🟢 95.1ms 🟢 97.4ms +2.4%
 ↳ emit/@typespec/openapi3/write 🟢 14.0ms 🟢 14.5ms +3.3%

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

tadelesh and others added 5 commits July 13, 2026 16:51
Add support for benchmarking specs that live in another repo (e.g. azure-rest-api-specs). A spec source is either a local directory with main.tsp or an external-spec directory with spec.json; the runner discovers both via --specs-dir and produces one results file. External specs are sparse-checked-out into .external (git-ignored) and compiled against this workspace's packages, so results reflect local library changes; each external spec's tspconfig.yaml (copied into the checkout) controls the emitters/linter measured. store-results and upload-pr-comment gain --results-dir (and --title/--comment-file) so groups can be stored/commented separately; the data-branch push rebases and retries to tolerate concurrent writers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each external spec is a directory with spec.json (source) and tspconfig.yaml (emit TCGC + ARM ruleset), pulled from azure-rest-api-specs at latest.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a Main baseline / External specs switch to the benchmarks page. The External view reads external-results/history.json and shows a single chart switchable between by-emitter (one line per spec) and by-spec (one line per emitter) comparison modes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Factor the run and comment logic into reusable workflows (benchmark-run.yml, benchmark-comment-run.yml). benchmark.yml (main) and benchmark-external.yml instantiate the run template with their own parameters; benchmark-comment.yml and benchmark-comment-external.yml instantiate the comment template. Each spec group is an independent workflow, avoiding duplicated steps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tadelesh tadelesh changed the title feat(benchmark): external-specs track with separate dataset and dashboard Benchmark external specs (azure-rest-api-specs) with a separate dashboard Jul 13, 2026
@tadelesh tadelesh marked this pull request as ready for review July 13, 2026 08:52
@tadelesh

Copy link
Copy Markdown
Member Author

@timotheeguerin this is ready for review — implements the external-spec benchmarking we discussed in #4801.

Summary of the approach:

  • External specs are just another kind of benchmark spec (a directory with spec.json + tspconfig.yaml); --specs-dir selects which set to run. The built-in/external distinction lives in CI and the dashboard, not in the tool.
  • External specs track main (no pinning), compile against the workspace packages, and each carries its own tspconfig.yaml (emitters + linter to measure).
  • Results are stored in a separate external-results/ directory and shown in a dedicated External specs dashboard view (by-emitter / by-spec modes), kept out of the main baseline.
  • The run/comment workflows are reusable templates instantiated per group (main + external), so no duplicated CI logic.

Included external specs: compute, web (AppService), network (ARM), measuring TCGC + the ARM ruleset. Happy to adjust the set or the per-emitter/graph layout.

@timotheeguerin timotheeguerin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving, didn't check too much the code, will check what the benchmark looks like after it runs and we'll tweak as needed

@tadelesh tadelesh added this pull request to the merge queue Jul 14, 2026
@tadelesh tadelesh removed this pull request from the merge queue due to a manual request Jul 14, 2026
@tadelesh tadelesh added this pull request to the merge queue Jul 14, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Jul 14, 2026
@tadelesh tadelesh added this pull request to the merge queue Jul 14, 2026
Merged via the queue into main with commit 3497e82 Jul 14, 2026
28 checks passed
@tadelesh tadelesh deleted the benchmark branch July 14, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

eng meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants