Files
RustPython/.github/workflows/codspeed.yaml
T
Jeong, YunWon ba19382018 ci: hold a CodSpeed run to the machine main's baseline was measured on (#8644)
* ci: hold a CodSpeed run to the machine main's baseline was measured on

CodSpeed compares a run against a base run and refuses to call the
comparison meaningful when the two ran on different machines: the runner
uploads a `SystemInfo` record beside the profile carrying the OS, the
architecture, the CPU's vendor id, brand and flags, the physical core
count and the installed memory, and a hosted pool hands out whatever
machine is free. A simulated measurement is fixed against how fast the
machine is, but not against what it makes the process execute -- glibc
selects `memcpy` and the string routines through IFUNC on CPU flags, a
new stable rustc emits different code, and these benchmarks run each
program under CPython through pyo3 as well as under RustPython, so the
runner's default interpreter is an input too.

`scripts/codspeed-environment.py` records those fields plus the rustc,
libc and CPython versions, and compares a run against a recording. The
benchmark job now restores the recording main last wrote, records over it
when the ref is main, and compares against it otherwise; the install,
build and measure steps carry `if: steps.environment.outputs.match !=
'false'`, so a run that drew a different machine finishes green having
uploaded nothing. A missing or unfetchable recording is read as "nothing
to disagree with" rather than as a mismatch.

Assisted-by: Claude

* ci: read an unreadable environment recording as not a match

A cache miss, an eviction or a cache-service outage leaves the reference file
absent, and the comparison then reported `match=true`: every guarded step ran
and the run uploaded a measurement without having identified the machine it was
taken on.

An absent recording now reports `match=false`, and says so as a `::warning`
rather than the `::notice` a mismatch emits, so a job that measures nothing
because it has nothing to compare against is distinguishable from one that
measures nothing because the machine differs.

Assisted-by: Claude
2026-09-04 01:28:25 +09:00

115 lines
4.2 KiB
YAML

on:
push:
branches: [main]
pull_request:
types: [unlabeled, opened, synchronize, reopened]
merge_group:
# `workflow_dispatch` allows CodSpeed to trigger backtest
# performance analysis in order to generate initial data.
workflow_dispatch:
name: CodSpeed
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_TERM_COLOR: always
CI: true
jobs:
benchmarks:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
name: Run benchmarks
runs-on: ubuntu-latest
timeout-minutes: 90
permissions:
contents: read
id-token: write # for OpenID Connect authentication with CodSpeed
env:
CACHE_PATHS: |
# https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
~/.cargo/.crates2.json
~/.cargo/.crates.toml
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
# The benchmarks are linked against libpython through the pyo3 dev-dependency.
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- name: Restore the machine main last measured on
# A recording that cannot be fetched is read as "none yet", which the step
# below treats as nothing to disagree with. Failing here instead would
# turn a cache outage into a red benchmark job.
continue-on-error: true
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: build/codspeed-environment-reference.json
key: codspeed-environment-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}
restore-keys: codspeed-environment-${{ runner.os }}-${{ runner.arch }}-
- name: Name the machine this run drew
id: environment
shell: bash
run: |
reference=build/codspeed-environment-reference.json
if [ "$GITHUB_REF" = refs/heads/main ]; then
args=(--record "$reference")
else
args=(--record build/codspeed-environment.json --reference "$reference")
fi
python3 scripts/codspeed-environment.py "${args[@]}" --github-output
- name: Restore cache
if: ${{ steps.environment.outputs.match != 'false' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ env.CACHE_PATHS }}
key: codspeed-v2-${{ hashFiles('**/Cargo.lock') }}
restore-keys: codspeed-v2-
continue-on-error: true
- name: Install cargo-codspeed
if: ${{ steps.environment.outputs.match != 'false' }}
run: cargo install cargo-codspeed --locked --version ^5
- name: Build the benchmark targets
if: ${{ steps.environment.outputs.match != 'false' }}
run: cargo codspeed build --locked --measurement-mode simulation -p rustpython -p rustpython-sre_engine
- name: Save cache
if: ${{ github.ref == 'refs/heads/main' }} # only save on main
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ env.CACHE_PATHS }}
key: codspeed-v2-${{ hashFiles('**/Cargo.lock') }}
continue-on-error: true
- name: Run the benchmarks
if: ${{ steps.environment.outputs.match != 'false' }}
uses: CodSpeedHQ/action@373d6868929f444bc08d901fd0eb0ad52a8875ea # v5.2.1
with:
mode: simulation
run: cargo codspeed run -p rustpython -p rustpython-sre_engine
- name: Record the machine this baseline was measured on
if: ${{ success() && github.ref == 'refs/heads/main' }}
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: build/codspeed-environment-reference.json
key: codspeed-environment-${{ runner.os }}-${{ runner.arch }}-${{ github.run_id }}