♻️ refactor(build): sort the builder's arguments in C (#790) #1245
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 👷 benchmark | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: ["main"] | |
| tags-ignore: ["**"] | |
| pull_request: | |
| concurrency: | |
| # Key push runs by commit, pull-request runs by ref. Every main commit is a base measurement some | |
| # open PR compares against, so it must run to completion; keying pushes by ref meant the next main | |
| # commit canceled the previous one's benchmark mid-run, leaving CodSpeed to diff against a partial | |
| # or stale base and report drift on untouched benchmarks. Pull-request runs still supersede their | |
| # own older commits. | |
| group: codspeed-${{ github.event_name == 'push' && github.sha || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| permissions: | |
| contents: read | |
| jobs: | |
| codspeed: | |
| name: 🚀 CodSpeed | |
| # OIDC only authenticates the repository registered with CodSpeed, so a fork's push runs fail with 401 Unauthorized | |
| if: github.repository == 'tox-dev/turbohtml' | |
| # The tox-dev org has no plan for CodSpeed's macro runners; the pins on the run step below hold the instruction | |
| # stream steady across GitHub's mixed Intel and AMD fleet instead. | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| id-token: write # OIDC lets the CodSpeed GitHub App authenticate this public repo without a token secret | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 # meson project() derives the version from git history | |
| persist-credentials: false | |
| - name: ⬇️ Install benchmark data | |
| run: git submodule update --init --depth 1 tools/html5lib-python tools/bench-data/war-and-peace | |
| - name: 🔄 Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| enable-cache: false | |
| # CodSpeed diffs this run against the base commit's run, measured whenever that commit landed, so an | |
| # interpreter patch released in between changes the instruction counts of untouched benchmarks. Pin the | |
| # exact build and bump it by hand. | |
| python-version: "3.14.7" | |
| # Build outside instrumentation so setup is not measured. Use LTO because fresh PGO profiles produce different | |
| # binaries; release wheels retain PGO+LTO. | |
| - name: 🏗️ Build the deterministic LTO extension and install benchmark deps | |
| run: | | |
| uvx --with tox-uv tox run -e codspeed --notest | |
| uv pip install --python .tox/codspeed/bin/python --reinstall --no-deps --no-build-isolation --editable . \ | |
| --config-settings=build-dir=.tox/codspeed/cbuild \ | |
| --config-settings=setup-args=-Dbuildtype=release \ | |
| --config-settings=setup-args=-Db_lto=true | |
| env: | |
| UV_PYTHON_PREFERENCE: only-managed | |
| # Callgrind counts every instruction glibc runs, and glibc picks its memcpy, memset, str*, and lazy-binding code | |
| # per CPU. GitHub hands each run an Intel Xeon or an AMD EPYC whose feature and preference bits select different | |
| # variants, so identical code counts differently between a base run and a head run. Turning every selector off | |
| # lands each runner on the same SSE2 baseline; the copy thresholds glibc derives from the runner's cache sizes | |
| # and the malloc arena count it derives from the core count are pinned for the same reason. The gate measures | |
| # instruction counts, so the slower baseline path costs nothing. | |
| - name: 📌 Pin glibc's per-CPU code paths | |
| run: | | |
| hwcaps=$(printf -- '-%s,' \ | |
| SSSE3 SSE4_1 SSE4_2 AVX AVX2 AVX512F AVX512VL AVX512BW AVX512DQ AVX512CD FMA FMA4 \ | |
| BMI1 BMI2 LZCNT POPCNT MOVBE ERMS RTM XSAVEC \ | |
| Fast_Unaligned_Load Fast_Unaligned_Copy Fast_Copy_Backward Fast_Rep_String Slow_BSF Slow_SSE4_2 \ | |
| Prefer_ERMS Prefer_FSRM Prefer_No_VZEROUPPER Prefer_No_AVX512) | |
| tunables=$(printf '%s:' \ | |
| "glibc.cpu.hwcaps=${hwcaps%,}" \ | |
| glibc.cpu.x86_data_cache_size=32768 \ | |
| glibc.cpu.x86_shared_cache_size=1048576 \ | |
| glibc.cpu.x86_non_temporal_threshold=786432 \ | |
| glibc.cpu.x86_rep_movsb_threshold=2048 \ | |
| glibc.cpu.x86_rep_stosb_threshold=2048 \ | |
| glibc.malloc.arena_max=1) | |
| echo "GLIBC_TUNABLES=${tunables%:}" >> "$GITHUB_ENV" | |
| - name: 🚀 Run benchmarks | |
| uses: CodSpeedHQ/action@373d6868929f444bc08d901fd0eb0ad52a8875ea # v5.2.1 | |
| env: | |
| # str hashes seed the dict and set probes the benchmarks walk; a fresh seed per run is a small run-to-run | |
| # term the CPU pins above do not cover. | |
| PYTHONHASHSEED: "0" | |
| with: | |
| exclude-allocations: true | |
| mode: simulation | |
| run: .tox/codspeed/bin/python -m pytest tests/benchmarks --codspeed |