VarBin: build views straight into a VarBinViewBuilder - #9127
Open
robert3005 wants to merge 1 commit into
Open
Conversation
Merging this PR will degrade performance by 48.15%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance ChangesTip Investigate this regression by commenting Comparing Footnotes
|
Appending a `VarBin` array to a `VarBinViewBuilder` canonicalized it first, which built the views, wrapped them in a `VarBinViewArray` the builder immediately unwrapped, and then had `append_varbinview_array` rewrite every view to rebase its buffer index onto the builder's. Number the buffer up front instead: `varbin_decode_views` takes the index the pushed buffer will land at, so the views come out already correct and the append is one view per row plus a buffer push. `varbin_to_canonical` now shares that helper, which also shrinks what `match_each_integer_ptype!` duplicates. A builder configured to compact still goes the canonical route — it chooses per buffer whether to keep, slice or rewrite it by measuring the finished views, and `push_buffer_and_adjusted_views` would bypass that. chunk_array_builder, fastest of 100 samples, 3 runs each: | benchmark (rows x chunks) | before | after | speedup | | ------------------------------------- | ------- | ------- | ------- | | varbin_to_varbinview_builder 10x1000 | 313 µs | 204 µs | 1.53x | | varbin_to_varbinview_builder 100x100 | 87.3 µs | 69.5 µs | 1.26x | | varbin_to_varbinview_builder 1000x10 | 58.6 µs | 54.8 µs | 1.07x | | varbin_opt_to_varbinview_bldr 10x1000 | 378 µs | 266 µs | 1.42x | | varbin_into_canonical 10x1000 | 357 µs | 253 µs | 1.41x | The last row is the control: it never touches the builder, so its gain is from the shared-helper extraction alone. Relative to it, the append itself drops from 0.88x to 0.81x of a canonicalization. Signed-off-by: Robert Kruszewski <github@robertk.io>
robert3005
force-pushed
the
rk/varbin-to-varbinview-builder
branch
from
August 1, 2026 10:30
30b5bcc to
d4aaedf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Appending a
VarBinarray to aVarBinViewBuildercanonicalized it first. That built the views, wrapped them in aVarBinViewArraythe builder immediately unwrapped, and then hadappend_varbinview_arrayrewrite every view to rebase its buffer index onto the builder's.Number the buffer up front instead:
varbin_decode_viewstakes the index the pushed buffer will land at, so the views come out already correct and the append is one view per row plus a buffer push.varbin_to_canonicalnow shares that helper, which also shrinks whatmatch_each_integer_ptype!duplicates — the array construction no longer expands once per integer width.A builder configured to compact still goes the canonical route. It chooses per buffer whether to keep, slice or rewrite it by measuring the finished views against the buffer, and
push_buffer_and_adjusted_viewstakes buffers as they are, so the fast path would silently opt it out.VarBinViewBuilder::compacts_buffersis the new accessor that guards it.Benchmarks
vortex-array/benches/chunk_array_builder.rs, fastest of 100 samples, 3 runs per side:chunked_varbin_to_varbinview_builder10×1000chunked_varbin_to_varbinview_builder100×100chunked_varbin_to_varbinview_builder1000×10chunked_varbin_opt_to_varbinview_builder10×1000chunked_varbin_into_canonical10×1000The last row is the control — it never touches the builder, so its gain comes from the shared-helper extraction alone. Relative to it, the append itself drops from 0.88x to 0.81x of a canonicalization. Most of the absolute win at high chunk counts is the smaller macro expansion; the rest is the skipped view rewrite.
Checks
cargo nextest run -p vortex-array -p vortex-fsst -p vortex-zstd -p vortex-onpair -p vortex-mask— 3377 passedcargo clippy -p vortex-array --all-targets --all-features— cleancargo +nightly fmt --allappend_varbin_to_varbinview_builder(interleaves VarBin appends with staged in-progress buffers and a VarBinView append, so buffer numbering is exercised) andappend_varbin_to_a_compacting_builder_still_compacts.🤖 Generated with Claude Code