Repository navigation
Add a workflow that backfills benchmark history #1611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| name: benchmarks-backfill | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| since: | ||
| description: Benchmark each master merge since this date (YYYY-MM-DD) that has no results | ||
| required: true | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| benchmark: | ||
| # One runner benchmarks every commit, so the differences between them come from the code rather | ||
| # than the hardware. Roughly 30 commits fit in the 6 hour job limit. | ||
| runs-on: ubuntu-24.04 | ||
| # The same as benchmarks.yml. | ||
| services: | ||
| postgres: | ||
| image: pgvector/pgvector:0.8.6-pg18 | ||
| env: | ||
| POSTGRES_PASSWORD: postgres | ||
| options: >- | ||
| --health-cmd "pg_isready --username postgres" | ||
| --health-start-period 30s | ||
| --health-start-interval 2s | ||
| ports: | ||
| - 5432:5432 | ||
| elasticsearch: | ||
| image: elasticsearch:9.5.2 | ||
| env: | ||
| ES_JAVA_OPTS: "-Xms250m -Xmx750m" | ||
| discovery.type: single-node | ||
| xpack.security.enabled: "true" | ||
| ELASTIC_PASSWORD: elastic | ||
| options: >- | ||
| --health-cmd "curl --fail --user elastic:elastic http://localhost:9200/" | ||
| --health-start-period 30s | ||
| --health-start-interval 2s | ||
| ports: | ||
| - 9200:9200 | ||
| env: | ||
| DJANGO_DATABASE_URL: postgres://postgres:postgres@localhost:5432/django | ||
| DJANGO_ISIC_ELASTICSEARCH_URL: http://elastic:elastic@localhost:9200 | ||
| DJANGO_CELERY_BROKER_URL: amqp://localhost:5672/ | ||
| DJANGO_CACHE_URL: redis://localhost:6379/0 | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| fetch-depth: 0 | ||
| # This job runs each commit's code and dependencies, so it keeps no credentials. | ||
| persist-credentials: false | ||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 | ||
| - name: Increase maintenance_work_mem for pgvector | ||
| run: psql -c "ALTER SYSTEM SET maintenance_work_mem = '512MB'" -c "SELECT pg_reload_conf();" | ||
| env: | ||
| PGHOST: localhost | ||
| PGUSER: postgres | ||
| PGPASSWORD: postgres | ||
| - name: Benchmark commits without results | ||
| # Each commit runs the current benchmarks on its own locked dependencies, the way tox's | ||
| # benchmark environment does. A commit can predate both. | ||
| run: | | ||
| benchmark_group=$(git show "$GITHUB_SHA:pyproject.toml" \ | ||
| | python3 -c "import sys, tomllib; print(*tomllib.load(sys.stdin.buffer)['dependency-groups']['benchmark'], sep=',')") | ||
| # Without a time, git uses the current time of day. | ||
| shas=$(git log --first-parent --since="$SINCE 00:00" --format=%H | jq --raw-input --null-input --raw-output \ | ||
| --rawfile data <(git show origin/gh-pages:benchmarks/data.js) \ | ||
| '[inputs] - [$data | ltrimstr("window.BENCHMARK_DATA = ") | fromjson | .entries.Benchmark[].commit.id] | .[]') | ||
| if [ -z "$shas" ]; then | ||
| echo "::error::Every master merge since $SINCE has results." | ||
| exit 1 | ||
| fi | ||
|
|
||
| mkdir "$RUNNER_TEMP/reports" | ||
| for sha in $shas; do | ||
| git checkout --quiet --force "$sha" | ||
| git checkout "$GITHUB_SHA" -- benchmarks isic/settings/benchmark.py | ||
| uv run --locked --extra development --no-default-groups --group test --with "$benchmark_group" \ | ||
| pytest benchmarks --ds=isic.settings.benchmark --no-cov \ | ||
| --benchmark-disable-gc --benchmark-group-by=func --benchmark-columns=min,median,iqr,rounds \ | ||
| --benchmark-json="$RUNNER_TEMP/reports/$sha.json" \ | ||
| || echo "$sha" >> "$RUNNER_TEMP/failed" | ||
| done | ||
| git checkout --quiet --force "$GITHUB_SHA" | ||
| env: | ||
| SINCE: ${{ inputs.since }} | ||
| PYTHONPATH: ${{ github.workspace }} | ||
| - name: Upload results | ||
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | ||
| with: | ||
| name: reports | ||
| path: ${{ runner.temp }}/reports | ||
| if-no-files-found: error | ||
| - name: Check for failed commits | ||
| run: | | ||
| if [ -s "$RUNNER_TEMP/failed" ]; then | ||
| echo "::error::The benchmarks failed for $(paste -sd ' ' "$RUNNER_TEMP/failed")." | ||
| exit 1 | ||
| fi | ||
| publish: | ||
| needs: benchmark | ||
| # Record the commits that worked, even when others failed. | ||
| if: ${{ !cancelled() }} | ||
| runs-on: ubuntu-24.04 | ||
| permissions: | ||
| # The job pushes the results to the gh-pages branch. | ||
| contents: write | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| # history.py reads each commit's message. | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
| - name: Checkout gh-pages | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| ref: gh-pages | ||
| path: gh-pages | ||
| - name: Download results | ||
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | ||
| with: | ||
| name: reports | ||
| path: reports | ||
| - name: Record results | ||
| run: | | ||
| for report in reports/*.json; do | ||
| python3 benchmarks/history.py record "$report" gh-pages/benchmarks/data.js | ||
| done | ||
| - name: Push results | ||
| working-directory: gh-pages | ||
| run: | | ||
| # See benchmarks.yml. | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||
| git add benchmarks | ||
| git commit --message "Record backfilled benchmarks since $SINCE" | ||
| git push | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift Retry publication against the latest If 🤖 Prompt for AI Agents |
||
| env: | ||
| SINCE: ${{ inputs.since }} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Lock the added benchmark dependencies.
benchmark_groupcomes from the triggering revision, not the commit under test.--withresolves those requirements in a separate environment that can override project dependencies;--lockedonly checks the commit's project lockfile. A later dependency release can therefore change a rerun's benchmark environment and results for the same commit. Install the benchmark requirements at versions exported from a chosen lockfile, including their transitive dependencies. (docs.astral.sh)🤖 Prompt for AI Agents