Skip to content

Run benchmarks on CodSpeed in CI#13

Open
kinto0 wants to merge 8 commits into
mainfrom
codspeed-ci
Open

Run benchmarks on CodSpeed in CI#13
kinto0 wants to merge 8 commits into
mainfrom
codspeed-ci

Conversation

@kinto0

@kinto0 kinto0 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Add a CodSpeed GitHub Actions workflow so the landed criterion benchmarks run continuously: instruction-count (simulation) mode for the deterministic microbenchmarks, walltime mode for the heavy real-world PyTorch benchmarks (which must not run under Valgrind).

Swap the criterion dev-dependency to codspeed-criterion-compat (aliased back to criterion) so the existing bench harness emits CodSpeed measurements under cargo codspeed while behaving like plain criterion otherwise, and add a [profile.bench] that drops LTO/single-codegen-unit to keep the CI build within runner memory limits.

Summary

Fixes #XXXX

Test Plan

@codspeed-hq

codspeed-hq Bot commented Jul 23, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

🆕 10 new benchmarks

Performance Changes

Mode Benchmark BASE HEAD Efficiency
🆕 Simulation inferred_typed_dict_64 N/A 750 µs N/A
🆕 Simulation exhaustive_match_48 N/A 423.1 ms N/A
🆕 Simulation enum_member_reads_512 N/A 21.2 ms N/A
🆕 Simulation isinstance_chain_64 N/A 300.7 ms N/A
🆕 Simulation overload_resolution_10x20 N/A 5.7 ms N/A
🆕 Simulation protocol_binding_mismatch_100x10 N/A 13 ms N/A
🆕 Simulation smoke N/A 339.3 µs N/A
🆕 Simulation typevar_join_256 N/A 6.7 ms N/A
🆕 Simulation union_pattern_read_32 N/A 83.6 ms N/A
🆕 Simulation variadic_any_call_256 N/A 893.7 µs N/A

Comparing codspeed-ci (286e049) with main (5c755c4)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (21ed80d) during the generation of this report, so 5c755c4 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

kinto0 added 2 commits July 23, 2026 12:49
Add a CodSpeed GitHub Actions workflow so the landed criterion benchmarks
run continuously: instruction-count (simulation) mode for the deterministic
microbenchmarks, walltime mode for the heavy real-world PyTorch benchmarks
(which must not run under Valgrind).

Swap the `criterion` dev-dependency to `codspeed-criterion-compat` (aliased
back to `criterion`) so the existing bench harness emits CodSpeed
measurements under `cargo codspeed` while behaving like plain criterion
otherwise, and add a `[profile.bench]` that drops LTO/single-codegen-unit to
keep the CI build within runner memory limits.
configure() otherwise spawns python3 subprocesses to probe the interpreter and
site-packages during state init. Under CodSpeed's instrumented (Valgrind)
instrument those syscalls (~65 execve, ~300ms) land in the measured region,
triggering the "cannot instrument system calls" warning and polluting
instruction counts. The snippets only use stdlib, served from bundled in-memory
typeshed, so no interpreter or site-packages are needed.
The walltime job ran `cargo codspeed run --mode walltime` but built with
`cargo codspeed build` (default instrumentation mode), so no walltime-built
benchmarks existed and the run failed with "No benchmarks found for the walltime
mode". Pass `-m walltime` to the build so it matches the run mode.
@github-actions github-actions Bot added size/m and removed size/m labels Jul 23, 2026
CodSpeed CI installs the latest cargo-codspeed (v5.0.1), but the compat
crate was pinned to major v2. Walltime result collection requires the
compat layer and the cargo-codspeed binary to share a major version, so
the walltime job failed with a version-incompatibility error. Align the
compat crate (and its transitive codspeed runtime) to v5.
@github-actions github-actions Bot added size/l and removed size/m labels Jul 23, 2026
Under CodSpeed's instrumented (Valgrind) instrument, dispatching the
check to a rayon pool — even a single-thread one — parks the measured
thread on a futex for the full check while a worker runs it. That
blocking cross-thread syscall can't be instrumented, so CodSpeed drops
it from the measure and warns ("46 system calls, 304.7ms").

Add a ThreadCount::Inline mode that builds no rayon pool, so spawn_many
runs the work directly on the calling thread, and use it for the micro
benchmarks. All work then stays on the measured thread with no handoff.
kinto0 added 3 commits July 23, 2026 17:11
The type checker times every step, run, and module load with Instant::now()/
elapsed() to populate telemetry counters. Instant::now() reads CLOCK_MONOTONIC
via the vDSO, so it is nearly free normally — but under Valgrind (CodSpeed's
instrumented instrument) the vDSO is bypassed and each reading becomes a real
clock_gettime syscall. A single check makes ~34 of them; CodSpeed cannot
instrument syscalls, so they are dropped from the measure and trigger a warning.

Add a Timer type in pyrefly_util gated by a global flag (default enabled, so
telemetry is unchanged) and route the hot-path timers through it. When disabled
the timer never reads the clock, so no clock_gettime is issued.
TaskHeap and per-module step computation call Condvar::notify_all() after every
work item / step completes. notify_all() issues a futex wake syscall even when
no thread is parked, which under CodSpeed's Valgrind instrument cannot be
instrumented (~7 futex per check in the single-threaded case).

Track the parked-waiter count under the same lock that guards the wait, and only
wake when it is non-zero. The count is read and mutated under the lock, so
skipping the wake is race-free: a thread that has not yet parked cannot have
incremented the count, and it re-checks the predicate under the lock before
waiting.
With timers gate-able, turn them off in the micro benchmark's shared state so
CodSpeed's instrumented instrument sees no clock_gettime syscalls in the measured
region. Combined with the condvar-wake guard, a measured check now issues zero
syscalls (previously 41: ~34 clock_gettime + ~7 futex).
@github-actions github-actions Bot added size/xl and removed size/l labels Jul 24, 2026
@github-actions

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant