Skip to content

ci(codspeed): the memory job pins its thread pool, because peak is a race - #579

Merged
FBumann merged 1 commit into
mainfrom
ci/pin-the-memory-jobs-thread-pool
Aug 11, 2026
Merged

FBumann merged 1 commit into
mainfrom
ci/pin-the-memory-jobs-thread-pool

Conversation

@FBumann

@FBumann FBumann commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

One env var on the memory job. POLARS_MAX_THREADS: 1.

Why

The build is deterministic given a pool size — repeated runs produce identical chunk counts and identical bytes. Peak is not, because peak is max simultaneous liveness, and whether two morsels are alive at the same instant is scheduling.

transport/s, eight runs per arm, whole-process peak:

pool peak run-to-run spread
1 176.5–179.1 MB 1.5%
4 194.3–200.4 MB 3.2%
8 215.7–223.4 MB 3.6%

The level moves further than the spread does. Per-thread buffers dwarf a small model — 176 → 216 MB for a model whose frames total 4.27 MB — and chunk count rises with the pool for identical data:

sector/s:     4 chunks @ 1 thread     590,000 bytes
              7 chunks @ 2 threads    590,000 bytes
             13 chunks @ 4 threads    590,000 bytes
             25 chunks @ 8 threads    590,000 bytes

memray counts allocations, so an unpinned pool measures the runner as much as the code. That is the s-rung instability visible on #578 — a pull request whose entire diff is a YAML comment, which moved four benchmarks across a 30-point range (transport-s-lp +18.16%, sector-s-highs −12.15%).

Scope, and what is not here

Memory job only. The walltime job stays multi-threaded: polars is multi-threaded native code, single-threading it would measure something nobody runs, and its macro runner is dedicated hardware whose pool is already stable.

PYTHONHASHSEED is not pinned. Five seeds produced byte-identical chunk counts and sizes — it would be a knob added on plausibility rather than evidence.

The cost, stated

This puts a step in the series at this commit. Points before and after are not comparable and nothing makes them so. The trade is deliberate: this job exists to make a series readable, and bench.yml with docs/benchmarks.md own the honest multi-threaded peak measured as RSS.

Follow-up worth testing separately: with one thread sector/s drops from 25 chunks to 4, so allocation counts fall sharply — the m rung may now fit under CodSpeed's ~2M-allocation guidance that forced this job onto s. m is the rung where things are measurable.

🤖 Generated with Claude Code

…race

The build is deterministic given a pool size: repeated runs produce identical
chunk counts and identical bytes. Peak is not, because peak is max simultaneous
liveness and whether two morsels are alive at the same instant is scheduling.
Measured on transport/s, eight runs per arm: spread 1.5% at one thread, 3.2% at
four, 3.6% at eight.

The level moves further than the spread. Per-thread buffers dwarf a small
model -- 176 MB, 194 MB, 216 MB at 1, 4 and 8 threads for a model whose frames
total 4.27 MB -- and chunk count rises with the pool for the same data
(sector/s: 4, 7, 13, 25 chunks at 1, 2, 4, 8, all at 590,000 bytes). memray
counts allocations, so an unpinned pool measures the runner as much as the code.
That is the s-rung instability seen on #578, a pull request whose entire diff is
a YAML comment and which moved four benchmarks across a 30-point range.

Only the memory job. The walltime job stays multi-threaded: polars is
multi-threaded native code, single-threading it would measure something nobody
runs, and its macro runner is dedicated hardware whose pool is already stable.

PYTHONHASHSEED is not pinned beside it. Five seeds produced byte-identical chunk
counts and sizes, so it would be a knob added on plausibility.

This puts a step in the series at this commit; points before and after are not
comparable and nothing makes them so. The trade is deliberate -- this job exists
to make a series readable, and bench.yml with docs/benchmarks.md own the honest
multi-threaded peak measured as RSS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codspeed

codspeed Bot commented Aug 11, 2026

Copy link
Copy Markdown

Merging this PR will regress 2 benchmarks

⚡ 2 improved benchmarks
❌ 2 regressed benchmarks
✅ 10 untouched benchmarks
⏩ 38 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Memory test_emit[sector-s-lpspec-highs] 4.3 MB 5 MB -13.77%
❌ Memory test_emit[profiled-s-lpspec-lp] 24.4 MB 27 MB -9.65%
⚡ Memory test_emit[nodal-s-lpspec-lp] 6.9 MB 5.9 MB +18.1%
⚡ Memory test_emit[sector-s-lpspec-lp] 5.6 MB 5 MB +12.05%

Tip

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


Comparing ci/pin-the-memory-jobs-thread-pool (08f6cd9) with main (b71ef49)

Open in CodSpeed

Footnotes

  1. 38 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. ↩

@FBumann
FBumann merged commit 0d23ffb into main Aug 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant