Commit 5abaf98
Fix flaky CodSpeed microbenchmarks (#8742)
A small pool of microbenchmarks flips ±10-35% between two fixed values
on unrelated PRs (including docs-only and lockfile-only changes),
spamming every CodSpeed report. This PR fixes them (and removes only 1
benchmark). No `#[cfg(codspeed)]` gating; CI and local runs stay
identical. One commit per benchmark.
## Changes
- **mimalloc as global allocator** in the 5 flaky `vortex-array` bench
files: `chunk_array_builder`, `dict_compress`, `varbinview_compact`,
`compare`, `binary_ops`
- **`bitwise_not_vortex_buffer_mut`**: drop the 128/1024/2048 sizes
(measured only harness overhead)
- **`slice_empty_vortex`**: rewrite as a 1024-iteration tight loop,
renamed `slice_empty_tight_loop_vortex`
- **`rebuild_naive` (vortex-zstd)**: the one benchmark removed instead
of fixed — its cost is dominated by zstd-internal copies (glibc
`ifunc`-resolved `memcpy`) that no bench-level change can stabilize, its
fixture is degenerate (a 4-string dictionary with all-zero offsets), and
ListView rebuild is already benchmarked across element types and list
shapes in `vortex-array/benches/listview_rebuild.rs`. The crate's
now-unused `divan` dev-dependency goes with it.
<details>
<summary>Which benchmarks were flaky, and the evidence</summary>
Identified by reading the CodSpeed comments on the ~47 PRs merged since
June 25 (post-#8490). The tell: the same benchmark flipping between the
same two values, in both directions, on PRs that can't have affected it
— including deny.toml-only (#8712, #8716), uv.lock-only (#8732),
docs-only (#8737, #8728, #8685), and CI-YAML-only (#8660, #8683)
changes.
| Benchmark | Evidence |
|---|---|
| `bitwise_not_vortex_buffer_mut[128/1024/2048]` | ~half of all PRs —
worst offender |
| `chunked_varbinview_*` ×4 | ~20 PRs, both directions |
| `chunked_bool_canonical_into[(1000,10)]` | ~2× flips (16µs ↔ 35µs) on
4 PRs |
| `encode_varbin`, `encode_varbinview` | ~12 PRs;
`encode_varbinview[(10000,4)]` also flipped on an earlier revision of
this PR |
| `compact`, `compact_sliced` (90%-utilization args) | ~8 PRs |
| `compare_int_constant` | ±11.1% verbatim on ≥9 PRs |
| `eq_i64_constant` | same ±11% signature incl. docs-only PR |
| `slice_empty_vortex` | -14.66% verbatim on ~13 PRs |
| `rebuild_naive` (vortex-zstd) | ~10 PRs, both directions |
Watch list (left alone, below the ≥3-independent-sightings bar):
`copy_nullable`/`copy_non_nullable[65536]` in `cast_decimal.rs`,
`true_count_vortex_buffer[128]`.
</details>
<details>
<summary>Root causes and why each fix matches</summary>
- **Allocation in the timed region** → glibc malloc's code differs
across CodSpeed runner images, so alloc-heavy benchmarks trace
differently for byte-identical Vortex code. Vendored mimalloc removes
glibc malloc from the trace. Empirical support: the only three bench
files already using mimalloc (`single_encoding_throughput`,
`common_encoding_tree_throughput`, `row_encode`) are the most
alloc-heavy suites in the repo and were never flagged once in the 47-PR
window.
- **Sub-microsecond work** → the measurement is fixed harness overhead
plus binary code layout, which shifts with any unrelated change. Fix by
making the operation dominate: the in-place NOT (no alloc, no copy)
keeps only sizes where the loop dominates; the empty slice runs 1024×
per iteration, mirroring the neighboring `slice_tight_loop_vortex`.
- **Environment-bound and low-signal** → `rebuild_naive`, per the
justification above: unfixable at the bench level and redundant with the
vortex-array ListView rebuild suite, so removed.
</details>
<details>
<summary>Validation: A/A reruns and a stacked canary PR</summary>
- **Expected one-time step changes on this PR**: swapping the allocator
changes the trace of every benchmark in the touched files, so this PR's
report shows a few ±10-20% level shifts (including on never-flaky
`encode_primitives`, which just shares a file). These need a one-time
acknowledgment on the CodSpeed dashboard; after merge every PR compares
mimalloc-vs-mimalloc.
- **A/A reruns** (same bench binaries measured three times, on separate
runners and commits): every value reproduced exactly — 211.5µs, 137.1µs,
14.6µs, 26.3µs — with zero new flags across 1656 benchmarks.
- **Canary #8743** (a #8681-style cold-string change stacked on this
branch — the class of change that used to collect five false flags):
**Performance Gate Passed**, `✅ 1660 untouched`, zero changes reported.
</details>
No public API changes; benchmark-only.
https://claude.ai/code/session_01T6PPcdrqcNeUkfi1EGd4oC
---------
Signed-off-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>1 parent 2f18a4c commit 5abaf98
11 files changed
Lines changed: 37 additions & 67 deletions
File tree
- encodings/zstd
- benches
- vortex-array
- benches
- vortex-buffer/benches
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
38 | 37 | | |
39 | 38 | | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
| 88 | + | |
88 | 89 | | |
89 | 90 | | |
90 | 91 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
26 | 30 | | |
27 | 31 | | |
28 | 32 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
25 | 29 | | |
26 | 30 | | |
27 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
28 | 32 | | |
29 | 33 | | |
30 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
23 | 27 | | |
24 | 28 | | |
25 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
22 | 26 | | |
23 | 27 | | |
24 | 28 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
246 | 246 | | |
247 | 247 | | |
248 | 248 | | |
249 | | - | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
250 | 255 | | |
251 | 256 | | |
252 | 257 | | |
| |||
0 commit comments