Skip to content

Commit cb2e2c9

Browse files
Improve benchmark dashboard UI (#4427)
## Changes ### Benchmark data pipeline (`packages/benchmark/src/generate-history.ts`) - Added `specMetrics` per-entry and `specNames` to `HistoryData` for per-spec drill-down ### Dashboard UI (`website/src/components/benchmarks/`) - **Per-spec filtering** — dropdown to view individual spec or averaged data - **Time range filter** — Last 30 days / 90 days / All time - **Dark mode support** — replaced hardcoded inline styles with CSS using Fluent UI variables - **Better x-axis** — shows dates instead of commit SHAs; commit hash + GitHub link in tooltips - **Loading/error UX** — CSS spinner, retry button, improved error messages - **URL state sync** — tab, spec, and time range reflected in URL params for shareable links ### Files changed - `packages/benchmark/src/generate-history.ts` — per-spec metrics in history.json - `website/src/components/benchmarks/benchmark-dashboard.tsx` — full UI rewrite - `website/src/components/benchmarks/benchmark-dashboard.css` — new stylesheet (Fluent UI tokens) --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 0ecab62 commit cb2e2c9

11 files changed

Lines changed: 1369 additions & 381 deletions

File tree

.github/workflows/benchmark.yml

Lines changed: 32 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ on:
88
branches:
99
- main
1010
- release/*
11+
workflow_dispatch:
12+
inputs:
13+
backfill_from:
14+
description: "Backfill from: commit SHA or number of recent commits. Leave empty to run a normal benchmark."
15+
required: false
16+
type: string
17+
branch:
18+
description: "Data branch to store results (default: benchmark-data)"
19+
required: false
20+
type: string
21+
default: "benchmark-data"
1122

1223
permissions:
1324
contents: write
@@ -37,7 +48,19 @@ jobs:
3748
- name: Build
3849
run: pnpm -r --filter "@azure-tools/typespec-benchmark..." build
3950

51+
- name: Run backfill
52+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.backfill_from }}
53+
run: |
54+
node packages/benchmark/dist/src/cli.js backfill \
55+
--from ${{ inputs.backfill_from }} \
56+
--specs-dir packages/benchmark/specs \
57+
--iterations 15 \
58+
--warmup 1 \
59+
--branch ${{ inputs.branch }} \
60+
--push
61+
4062
- name: Run benchmarks
63+
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.backfill_from }}
4164
run: |
4265
node packages/benchmark/dist/src/cli.js run \
4366
--specs-dir packages/benchmark/specs \
@@ -50,95 +73,23 @@ jobs:
5073
- name: Store benchmark results
5174
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
5275
run: |
53-
COMMIT_SHA=${{ github.sha }}
54-
RESULTS_FILE="/tmp/benchmark-results.json"
55-
56-
# Configure git
57-
git config user.name "github-actions[bot]"
58-
git config user.email "github-actions[bot]@users.noreply.github.com"
59-
60-
# Check if benchmark-data branch exists
61-
if git ls-remote --exit-code --heads origin benchmark-data > /dev/null 2>&1; then
62-
git fetch origin benchmark-data
63-
git worktree add /tmp/bench-data origin/benchmark-data
64-
else
65-
# Create orphan branch
66-
git worktree add --detach /tmp/bench-data
67-
cd /tmp/bench-data
68-
git checkout --orphan benchmark-data
69-
git rm -rf . 2>/dev/null || true
70-
mkdir -p results
71-
echo "# Benchmark Data" > README.md
72-
echo "" >> README.md
73-
echo "This branch stores TypeSpec benchmark results. Do not merge into main." >> README.md
74-
git add README.md
75-
git commit -m "Initialize benchmark-data branch"
76-
cd -
77-
fi
78-
79-
# Copy results
80-
mkdir -p /tmp/bench-data/results
81-
cp "$RESULTS_FILE" "/tmp/bench-data/results/${COMMIT_SHA}.json"
82-
cp "$RESULTS_FILE" "/tmp/bench-data/results/latest.json"
83-
84-
# Generate aggregated history.json for the website
85-
cd "$GITHUB_WORKSPACE"
86-
node packages/benchmark/dist/src/cli.js generate-history /tmp/bench-data/results/history.json --dir /tmp/bench-data/results
87-
88-
# Commit and push
89-
cd /tmp/bench-data
90-
git add results/
91-
git commit -m "Benchmark results for ${COMMIT_SHA}"
92-
git push origin HEAD:benchmark-data
76+
node packages/benchmark/dist/src/cli.js store-results \
77+
--results /tmp/benchmark-results.json \
78+
--commit ${{ github.sha }}
9379
9480
# On PR: fetch baseline, compare, and upload as artifact for the comment workflow
95-
- name: Fetch baseline
81+
- name: Generate PR comment
9682
if: github.event_name == 'pull_request'
97-
id: fetch-baseline
98-
run: |
99-
if git ls-remote --exit-code --heads origin benchmark-data > /dev/null 2>&1; then
100-
git fetch origin benchmark-data
101-
git show origin/benchmark-data:results/latest.json > /tmp/benchmark-baseline.json 2>/dev/null && \
102-
echo "has_baseline=true" >> "$GITHUB_OUTPUT" || \
103-
echo "has_baseline=false" >> "$GITHUB_OUTPUT"
104-
else
105-
echo "has_baseline=false" >> "$GITHUB_OUTPUT"
106-
fi
107-
108-
- name: Compare benchmarks
109-
if: github.event_name == 'pull_request' && steps.fetch-baseline.outputs.has_baseline == 'true'
11083
run: |
111-
# Generate markdown comment
112-
node packages/benchmark/dist/src/cli.js compare \
113-
--baseline /tmp/benchmark-baseline.json \
114-
--current /tmp/benchmark-results.json \
115-
--format markdown \
116-
--output /tmp/benchmark-comment.md
117-
118-
# Print console summary
119-
node packages/benchmark/dist/src/cli.js compare \
120-
--baseline /tmp/benchmark-baseline.json \
121-
--current /tmp/benchmark-results.json
122-
123-
- name: Generate no-baseline comment
124-
if: github.event_name == 'pull_request' && steps.fetch-baseline.outputs.has_baseline != 'true'
125-
run: |
126-
cat > /tmp/benchmark-comment.md << 'EOF'
127-
## ⚡ Benchmark Results
128-
129-
No baseline found on the `benchmark-data` branch. Benchmark results will be stored after merging to `main`.
130-
EOF
131-
132-
- name: Save PR number
133-
if: github.event_name == 'pull_request'
134-
run: echo "${{ github.event.number }}" > /tmp/benchmark-pr-number.txt
84+
node packages/benchmark/dist/src/cli.js upload-pr-comment \
85+
--results /tmp/benchmark-results.json \
86+
--pr-number ${{ github.event.number }} \
87+
--output-dir /tmp/benchmark-artifacts
13588
13689
- name: Upload benchmark comment
13790
if: github.event_name == 'pull_request'
13891
uses: actions/upload-artifact@v7
13992
with:
14093
name: benchmark-comment
141-
path: |
142-
/tmp/benchmark-comment.md
143-
/tmp/benchmark-pr-number.txt
94+
path: /tmp/benchmark-artifacts/
14495
retention-days: 1

packages/benchmark/README.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,41 @@ Located in `specs/`:
7676

7777
The `.github/workflows/benchmark.yml` workflow:
7878

79-
- **On push to `main`**: Runs benchmarks and stores results to the `benchmark-data` branch
80-
- **On pull requests**: Runs benchmarks, compares with the latest `main` baseline, and posts a sticky PR comment with the comparison table
79+
- **On push to `main`**: Runs benchmarks and stores results to the `benchmark-data` branch via the `store-results` CLI command
80+
- **On pull requests**: Runs benchmarks, fetches the baseline, compares, and generates a PR comment via the `upload-pr-comment` CLI command
8181

8282
### Data storage
8383

8484
Results are stored on the `benchmark-data` orphan branch:
8585

8686
- `results/<commit-sha>.json` — per-commit results
8787
- `results/latest.json` — latest main baseline
88+
- `results/history.json` — aggregated history for the website
89+
90+
### Backfill historical data
91+
92+
To backfill benchmark results for past commits:
93+
94+
```bash
95+
# Backfill last 100 commits (default)
96+
node packages/benchmark/dist/src/cli.js backfill
97+
98+
# Backfill last 50 commits, then push
99+
node packages/benchmark/dist/src/cli.js backfill --from 50 --push
100+
101+
# Backfill from a specific commit to HEAD of main
102+
node packages/benchmark/dist/src/cli.js backfill --from abc1234
103+
104+
# Backfill a specific commit range
105+
node packages/benchmark/dist/src/cli.js backfill --from abc1234 --to def5678
106+
```
107+
108+
The backfill command:
109+
110+
1. Builds and saves the current benchmark CLI
111+
2. Checks out each historical commit, builds its dependencies, and runs benchmarks using the saved CLI
112+
3. Skips commits that already have results on the `benchmark-data` branch
113+
4. Commits all new results to the `benchmark-data` branch
88114

89115
## What gets measured
90116

0 commit comments

Comments
 (0)