Skip to content

♻️ refactor(build): sort the builder's arguments in C (#790) #1245

♻️ refactor(build): sort the builder's arguments in C (#790)

♻️ refactor(build): sort the builder's arguments in C (#790) #1245

Workflow file for this run

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