Skip to content

perf(buffer): read byte-aligned bit operands directly as words#8436

Merged
joseph-isaacs merged 3 commits into
vortex-data:developfrom
miniex:perf/bit-collect
Jun 16, 2026
Merged

perf(buffer): read byte-aligned bit operands directly as words#8436
joseph-isaacs merged 3 commits into
vortex-data:developfrom
miniex:perf/bit-collect

Conversation

@miniex

@miniex miniex commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Split out of #8425 so each perf change can be looked at on its own, as suggested by @joseph-isaacs. This is the "bit collect" half, no count fusion.

bitwise_binary_op only took the direct word path when both operands were 64-bit aligned, otherwise falling back to iter_padded. It now reads the backing bytes as u64 via as_chunks::<8> for any byte-aligned offset, leaving iter_padded for sub-byte offsets only. This also drops the from_trusted_len_iter unsafe for a safe BufferMut push.

Testing

cargo test -p vortex-buffer passes, plus a per-bit reference test (binary_op_matches_naive) across operand offsets and lengths. It also passes under miri (strict provenance). fmt + clippy --all-targets --all-features clean.


I'm Korean, so sorry if any wording reads a little awkward.

the direct word path only fired for 64-bit-aligned operands. it now reads the
bytes as `u64` via `as_chunks::<8>` for any byte-aligned offset, leaving
`iter_padded` for sub-byte.

Signed-off-by: Han Damin <miniex@daminstudio.net>
@codspeed-hq

codspeed-hq Bot commented Jun 15, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 24.7%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚡ 13 improved benchmarks
❌ 3 regressed benchmarks
✅ 1529 untouched benchmarks
⏩ 10 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation chunked_bool_canonical_into[(1000, 10)] 20.4 µs 35.6 µs -42.6%
Simulation chunked_varbinview_canonical_into[(1000, 10)] 161.6 µs 198 µs -18.38%
Simulation chunked_varbinview_into_canonical[(1000, 10)] 176.6 µs 213 µs -17.1%
Simulation bitwise_and_vortex_buffer[65536] 24.3 µs 15.1 µs +60.89%
Simulation bitwise_or_vortex_buffer[65536] 24.3 µs 15.2 µs +60.08%
Simulation bitwise_and_vortex_buffer[2048] 4.4 µs 2.9 µs +50.81%
Simulation bitwise_and_vortex_buffer[1024] 4.1 µs 2.8 µs +48.06%
Simulation bitwise_and_vortex_buffer[16384] 9.9 µs 6.7 µs +47.62%
Simulation bitwise_or_vortex_buffer[16384] 9.9 µs 6.8 µs +46.14%
Simulation bitwise_or_vortex_buffer[1024] 4 µs 2.8 µs +45.94%
Simulation bitwise_or_vortex_buffer[2048] 4.3 µs 3 µs +45.88%
Simulation bitwise_and_vortex_buffer[128] 4.7 µs 3.4 µs +38.44%
Simulation bitwise_or_vortex_buffer[128] 4.7 µs 3.4 µs +36.41%
Simulation bitwise_not_vortex_buffer_mut[128] 273.6 ns 215.3 ns +27.1%
Simulation bitwise_not_vortex_buffer_mut[1024] 333.9 ns 275.6 ns +21.17%
Simulation bitwise_not_vortex_buffer_mut[2048] 456.9 ns 398.6 ns +14.63%

Tip

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


Comparing miniex:perf/bit-collect (d1786df) with develop (e935986)

Open in CodSpeed

Footnotes

  1. 10 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.

Comment thread vortex-buffer/src/bit/ops.rs Outdated
Comment on lines 196 to 197
// bytes straight as words instead of shifting through `iter_padded`.
if left.offset().is_multiple_of(8) && right.offset().is_multiple_of(8) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// bytes straight as words instead of shifting through `iter_padded`.
if left.offset().is_multiple_of(8) && right.offset().is_multiple_of(8) {
// bytes straight as words instead of shifting through `iter_padded`.
// TODO(joe): make this into an iterator.
if left.offset().is_multiple_of(8) && right.offset().is_multiple_of(8) {

Can you add a todo to make this into an iterator

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe do this?

Comment thread vortex-buffer/src/bit/ops.rs Outdated
Comment on lines +201 to +212
let lhs = &left.inner().as_slice()[l_start..l_start + n_bytes];
let rhs = &right.inner().as_slice()[r_start..r_start + n_bytes];

let (lhs_words, lhs_tail) = lhs.as_chunks::<8>();
let (rhs_words, rhs_tail) = rhs.as_chunks::<8>();

let words = lhs_words
.iter()
.zip(rhs_words)
.map(|(l, r)| (u64::from_le_bytes(*l), u64::from_le_bytes(*r)))
.chain((!lhs_tail.is_empty()).then(|| (read_u64_le(lhs_tail), read_u64_le(rhs_tail))));
return combine_words(words, len, op);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will make LLVM generate better code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i check it!

@joseph-isaacs

Copy link
Copy Markdown
Contributor

I just merged in a fix to another crate from develop

the byte-aligned path used a `with_capacity` + push loop. build it from a
`TrustedLen` iterator instead so it pre-sizes and lets LLVM generate better code.

Signed-off-by: Han Damin <miniex@daminstudio.net>
@miniex

miniex commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

done, made it a TrustedLen iterator

@miniex miniex requested a review from joseph-isaacs June 16, 2026 10:01
@joseph-isaacs

joseph-isaacs commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

I was talking about the input too, You really have found the difference between an aligned and unaligned byte iterator. Lets land this and maybe we can have a follow up

@joseph-isaacs joseph-isaacs enabled auto-merge (squash) June 16, 2026 10:10
@joseph-isaacs joseph-isaacs added the changelog/performance A performance improvement label Jun 16, 2026

@joseph-isaacs joseph-isaacs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. I wonder if we can work this into an iterator left and right without a perf loss?

@joseph-isaacs joseph-isaacs merged commit 9b5447a into vortex-data:develop Jun 16, 2026
66 of 69 checks passed
@miniex

miniex commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for this. I wonder if we can work this into an iterator left and right without a perf loss?

thanks for merging! lets dig into that in a follow up.

also #8425 is the collect+count half stacked on this. i'll rebase it onto develop now that this landed so it's just the fuse, then it's ready for review.

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

Labels

changelog/performance A performance improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants