Skip to content

Address recurring CodSpeed warnings - #10839

Merged
connortsui20 merged 3 commits into
developfrom
ct/trusting-goodall-2kfoac
Oct 27, 2026
Merged

connortsui20 merged 3 commits into
developfrom
ct/trusting-goodall-2kfoac

Conversation

@connortsui20

@connortsui20 connortsui20 commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Summary

Every CodSpeed report carries the same warnings. This removes the ones with a cause in this repository: "no flamegraph", "unable to measure", and all of "dominated by system calls" except real file I/O.

Changes

  • Python 3.13 for the Python job. All 40 "no flamegraph" notes were the Python benchmarks. pytest-codspeed records Python frames only through the CPython perf trampoline, which exists from 3.12, and the job ran on 3.11. The 40 Python series moved once, because the interpreter changed and pytest-codspeed now runs each benchmark once before it measures.
  • No allocator system calls in measured iterations. A simulated benchmark is one cold iteration, and the simulation leaves system calls out of the measure. mimalloc returned freed memory to the OS on a 10 ms timer that the slow simulation crosses, and glibc (used by zstd) trimmed and regrew its heap with brk. The simulation job now sets MIMALLOC_PURGE_DELAY=-1, MALLOC_TRIM_THRESHOLD_ and MALLOC_TOP_PAD_. With the setup fixes below, this took the system-call warning from 15 benchmarks to 2 Python ones on this PR, and fixed bench_compare_primitive[(10000, 2)].
  • No one-time setup in measured iterations. ilike_contains and filter_run_end[len=4096_run=16_density=0.1] paid for process-wide setup: the first regex compilation and the session id interner, which read the CPU quota from cgroup files. Both bench binaries now run the operation once in main(), and the guide gains a rule against this mistake.
  • filter_bool.rs drops the 1000-row size. It did under 1 µs of work, and about half of filter_powerlaw_by_mostly_false[1000]'s iteration was mimalloc setting up a fresh page after the previous, larger case. CodSpeed reported no execution time for it.

Not addressed: "Walltime results may be unreliable" and "Base and head ran on different runner types" come from running walltime on self-hosted machines instead of CodSpeed Macro Runners. Two Python scans still read a file inside the measured iteration, which is real I/O.

How the causes were found

The benchmarks were built with --cfg codspeed and run under valgrind --tool=callgrind --instr-atstart=no -v --trace-syscalls=yes. CodSpeed starts and stops callgrind instrumentation around each measured iteration, and -v logs those switches, so the system calls between them are exactly the ones inside a measured iteration. With the changes, none of the measured iterations in like, run_end_filter, filter_bool and single_encoding_throughput (116 in all) makes a system call.

Checks run: cargo clippy --locked -p vortex-array on the three changed benches (after rebasing onto #10703, which moved RunEnd into vortex-array) with -D warnings, cargo +nightly-2026-09-10 fmt --check, yamllint --strict, typos, git diff --check, and the callgrind traces above. Not run: the CodSpeed jobs (they run on this PR).

https://claude.ai/code/session_01KF3pMFx7U5ngk8BzQQFS2W


Generated by Claude Code

@codspeed

codspeed Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 7 benchmarks

3 warnings

⚠️ Walltime results may be unreliable

Some benchmarks used the Walltime instrument outside CodSpeed Macro Runners, which can make the results inconsistent.

Learn more about Macro Runners

See affected benchmarks

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

⚡ 14 improved benchmarks
❌ 7 regressed benchmarks
✅ 2408 untouched benchmarks
⏩ 126 skipped benchmarks1
🗄️ 43 archived benchmarks run2

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Walltime threshold_neon[8] 1.4 µs 2.6 µs -45.99%
❌ Walltime filter_neon[8] 922 ns 1,516 ns -39.18%
❌ Walltime threshold_neon[64] 2.6 µs 4.2 µs -37.52%
❌ Walltime filter_neon[64] 1.8 µs 2.7 µs -34.65%
❌ CPU Simulation chunked_dict_primitive_canonical_into[f64, (1000, 1000, 10)] 141 µs 203.9 µs -30.82%
❌ Walltime threshold_neon[80] 3.5 µs 4.7 µs -26.06%
❌ Walltime filter_neon[80] 2.5 µs 3.3 µs -23.69%
⚡ CPU Simulation filter_run_end[len=4096_run=16_density=0.1] 153.9 µs 53.4 µs ×2.9
⚡ CPU Simulation density_sweep_random[0.001] 46.9 µs 19.3 µs ×2.4
⚡ CPU Simulation filter_powerlaw_by_correlated_runs[10000] 29.4 µs 13.9 µs ×2.1
⚡ CPU Simulation test_repeated_scan_scalar_at[int_float] 365.1 µs 307.8 µs +18.65%
⚡ CPU Simulation test_repeated_scan_scalar_at[int_str] 396.6 µs 335.2 µs +18.34%
⚡ CPU Simulation test_repeated_scan_scalar_at[int_str_float] 477.8 µs 410 µs +16.52%
⚡ CPU Simulation filter_powerlaw_by_power_law[250000] 182.9 µs 158.1 µs +15.67%
⚡ Walltime mul_u16_nonnull_avx512 12.5 µs 10.9 µs +15.42%
⚡ Walltime filter_avx2[80] 2 µs 1.7 µs +14.38%
⚡ CPU Simulation like_per_row_patterns 191.5 µs 168.1 µs +13.94%
⚡ Walltime subtract_shapes_avx512[(32768, PerRowPerRow)] 13.1 µs 11.6 µs +13.03%
⚡ CPU Simulation test_repeated_scan_filter[int] 2.7 ms 2.4 ms +12.29%
⚡ CPU Simulation test_repeated_scan_scalar_at[int] 235.4 µs 211.4 µs +11.32%
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing ct/trusting-goodall-2kfoac (83d7d47) with develop (fb4a037)

Open in CodSpeed

Footnotes

  1. 126 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. 43 benchmarks were run, but are now archived. If they were deleted in another branch, consider rebasing to remove them from the report. Instead if they were added back, click here to restore them. ↩

@connortsui20 connortsui20 changed the title Run the Python CodSpeed benchmarks on Python 3.13 Address recurring CodSpeed warnings Oct 26, 2026
@github-actions
github-actions Bot temporarily deployed to docs-preview/pr-10839 October 26, 2026 21:23 Inactive
@connortsui20
connortsui20 enabled auto-merge (squash) October 27, 2026 12:42
pytest-codspeed records Python frames only through the CPython perf
trampoline, which exists from Python 3.12. The job used 3.11 from
`.python-version`, so CodSpeed reported all 40 Python benchmarks as
having no flamegraph on every pull request. The extension targets the
stable ABI from 3.11, so it runs unchanged on 3.13.

Claude-Session: https://claude.ai/code/session_01KF3pMFx7U5ngk8BzQQFS2W
Signed-off-by: Claude <noreply@anthropic.com>
mimalloc returns freed memory to the OS 10 ms after a free. Under the
CodSpeed simulation, benchmarks run many times slower, so the purge of
one benchmark's memory can land in a later benchmark's single measured
iteration. That iteration then spends its time in `madvise` calls and
page faults, which the simulation leaves out, and CodSpeed reports it as
dominated by system calls or as measuring no time. Under Valgrind,
`MIMALLOC_PURGE_DELAY=-1` cut the `madvise` calls of the
`filter_powerlaw` benchmarks from 23 to 1.

Claude-Session: https://claude.ai/code/session_01KF3pMFx7U5ngk8BzQQFS2W
Signed-off-by: Claude <noreply@anthropic.com>
Tracing the measured regions under callgrind showed where the remaining
system calls and the empty measurement came from:

- `ilike_contains` and `filter_run_end[len=4096_run=16_density=0.1]`
  paid for one-time process setup (the first regex compilation and the
  session id interner, which read the CPU quota from the file system).
  Both bench binaries now run the operation once in `main()`.
- `zstd_compress_string` grew glibc's heap with `brk`. zstd allocates
  through glibc, which trims its heap after large frees. The simulation
  job now sets `MALLOC_TRIM_THRESHOLD_` and `MALLOC_TOP_PAD_`.
- `filter_powerlaw_by_mostly_false[1000]` did under 1 µs of work, and
  about half of its measured iteration was mimalloc setting up a fresh
  page after the previous, larger case. The 1000-row size is gone from
  `filter_bool.rs`.

The benchmarking guide gains a rule against leaving one-time setup to
the first measured iteration.

Claude-Session: https://claude.ai/code/session_01KF3pMFx7U5ngk8BzQQFS2W
Signed-off-by: Claude <noreply@anthropic.com>
@connortsui20
connortsui20 force-pushed the ct/trusting-goodall-2kfoac branch from 41576fd to 83d7d47 Compare October 27, 2026 12:45
@connortsui20
connortsui20 merged commit b9150dd into develop Oct 27, 2026
86 of 87 checks passed
@connortsui20
connortsui20 deleted the ct/trusting-goodall-2kfoac branch October 27, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants