Latest Results
Pin every `#[array_slots]` field to an explicit slot index (#9004)
## Rationale for this change
Follow-up to #8950, which landed the `#[array_slots]` macro with
variadic tail support.
The macro derives slot indices from **field declaration order**. That
makes the physical
storage layout an implicit consequence of how the struct happens to be
written: reordering
two fields, grouping related fields together, or inserting a new field
in the middle
silently renumbers the slots. Nothing in the source says which index a
field occupies, so
the change looks cosmetic in review while actually altering the layout
arrays are built
from and read back with.
Slot indices are a storage contract. They should be stated, not
inferred.
## What changes are included in this PR?
### Macro (`vortex-array-macros/src/lib.rs`)
Every field of an `#[array_slots]` struct must now carry a `#[slot(N)]`
attribute naming
the exact index it maps to ā `#[slot(N..)]` for a variadic
`Vec<ArrayRef>` tail:
```rust
#[array_slots(Chunked)]
pub struct ChunkedSlots {
#[slot(0)]
pub chunk_offsets: ArrayRef,
#[slot(1..)]
pub chunks: Vec<ArrayRef>,
}
```
The annotation ā not the declaration order ā drives the generated
constants, `from_slots`,
and `into_slots`. `into_slots` emits in annotation order, and `NAMES` /
`FIXED_NAMES` are
sorted by index, so declaration order becomes purely cosmetic. Because
indices are now
authoritative, the variadic tail no longer has to be the last *declared*
field.
`#[slot(..)]` is inert helper syntax consumed during expansion and
stripped from the
re-emitted struct.
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Co-authored-by: Claude <noreply@anthropic.com> bench: stop measuring harness overhead in nanosecond benchmarks
One divan bench_refs iteration carries a fixed ~146 instructions of
harness. Where the measured operation costs less than that, the reported
figure tracks the harness rather than the operation, and a small change
in harness cost swings it past CodSpeed s 10% flag threshold with the
measured code untouched. Per-iteration instruction counts (callgrind,
the same instrument class as CodSpeed Simulation) confirm the flagged
benchmarks are exactly the overhead-dominated ones:
true_count_vortex_buffer 1024: 187 Ir (78% harness) <- flagged
2048: 228 Ir (64% harness) <- flagged
16384: 802 Ir (18% harness)
65536: 2770 Ir (5% harness)
The fit is linear at ~0.04 Ir/bit with a ~146 Ir intercept, and no
report ever flagged 16384 or 65536. This also explains why #8861 did not
settle it: dropping 128 (97% harness) just promoted 1024 to worst.
- true_count: keep 16384 and 65536, where the popcount dominates.
- slice: BitBuffer::slice only adjusts an offset, a length and a
refcount, so cost is independent of length -- every size measured
exactly 125 Ir, which is why CodSpeed reported identical values for
[1024] and [16384] on #8749. Measure one length with enough slices per
iteration to dominate; varying the offset keeps them from folding
together. Per-slice cost is 144 Ir, 1.3% harness.
- binary_search: one search over 65536 elements is ~16 comparisons, and
at ~71% harness the two implementations measured 203 vs 206 Ir --
indistinguishable, defeating the comparison the benchmark exists for.
Searching 64 targets per iteration gives 1.0-1.5% harness and
separates them: 15133 Ir vortex vs 10010 Ir std.
varbinview_compact was left alone: compact[(4096, 90)] is 1069 Ir, only
14% harness, so its reports belong to the comparison-base problem fixed
in the preceding commit rather than to harness overhead.
Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ypCZPxvLuJK9FgWKF8U4Pclaude/codspeed-flake-rootcause Latest Branches
-10%
0%
agent/rename-scalar-fn-strictness -11%
adamg/try-fix-df-pq-benchmark Ā© 2026 CodSpeed Technology