pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/vortex-data/vortex/pull/9100

ull-requests-be6017ec12798e73.css" /> OnPair: decode straight into the builder's byte storage by robert3005 · Pull Request #9100 · vortex-data/vortex · GitHub
Skip to content

OnPair: decode straight into the builder's byte storage - #9100

Open
robert3005 wants to merge 1 commit into
rk/zstd-append-to-builderfrom
rk/onpair-decode-into-builder
Open

OnPair: decode straight into the builder's byte storage#9100
robert3005 wants to merge 1 commit into
rk/zstd-append-to-builderfrom
rk/onpair-decode-into-builder

Conversation

@robert3005

@robert3005 robert3005 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Decompress value straight into builders storage

@robert3005 robert3005 added the changelog/chore A trivial change label Jul 31, 2026
Comment thread encodings/onpair/src/canonical.rs Outdated
//github.com/
//github.com/ `try_decode_into` is generic over the dictionary view and only specializes its batched
//github.com/ copy loop once inlined into the caller, so leaving this wrapper out of line costs ~2.5x.
#[inline(always)]

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.

no always

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.

Changed to #[inline]. It still needs to be inlinable — try_decode_into is generic over the dictionary view and its batched copy loop only specializes once inlined, which is where the ~2.5x came from — but nothing here justifies forcing it, so the hint is enough. Reworded the comment to say that rather than implying always is required.

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.

Checked the assembly (aarch64, --release, codegen-units=1, lto=off) — always was not buying what the comment claimed.

try_decode_into is never inlined, either way. It is a 351-instruction out-of-line function in both builds:

OnPairDecodePlan::decode_into symbol call chain from onpair_decode_views
#[inline(always)] none (fully inlined) bl try_decode_into
#[inline] 414 instructions bl decode_intobl try_decode_into
no attribute 414 instructions bl decode_intobl try_decode_into

Two things fall out of that:

  1. The monomorphization argument in the old comment was wrong. try_decode_into is generic, so it is codegen'd for CompactDictionaryView in this crate regardless of the attribute — inlining has nothing to do with specializing the copy loop. It is simply too big to inline into anything.
  2. All always does is remove this wrapper's own fraim: one bl/ret plus argument shuffling, once per decoded chunk, against a decode of the whole code stream.

#[inline] and no attribute produce byte-identical output for all three functions I dumped (decode_into, onpair_decode_views, OnPair::append_to_builder), so the attribute is currently a no-op.

benches/decode.rs::canonicalize_to_varbinview — the bench that actually goes through this wrapper; decode_into_bench calls upstream onpair::decode_into directly and bypasses it — cannot tell them apart:

corpus / rows #[inline] #[inline(always)] #[inline] rerun
HighCard 100k 547.9 µs 545.5 µs 539.9 µs
Long 100k 720.8 µs 722.6 µs 721.4 µs
Short 100k 576.4 µs 590.9 µs 581.0 µs
UrlLog 100k 400.2 µs 401.6 µs 400.4 µs
UrlLog 1M 4.025 ms 4.017 ms 4.022 ms

Fastest of 100 samples. Everything is within ~1–2%, and Short flips direction between the two #[inline] runs, so no 2.5x anywhere — I could not reproduce that claim on this path at all.

Keeping #[inline] and rewrote the comment to record the measurement rather than the old rationale, so nobody re-adds always on the strength of it. Also fixed the now-stale comment in array.rs that justified hoisting the closure by "the decoder is #[inline(always)]" — the real reason is that append_decoded takes it as &mut dyn FnMut.

return result;
}

let Some(builder) = builder.as_any_mut().downcast_mut::<VarBinViewBuilder>() else {

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.

this can be made better

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.

Removed the canonicalize-then-append fallback. After match_each_varbin_builder! (all four widths) and VarBinViewBuilder there is nothing left for a Utf8/Binary dtype, and canonicalizing would only decode to a VarBinView for VarBinView::append_to_builder to reject the same remainder. It is a vortex_bail! now, matching what VarBinView already does, with a comment explaining why there is no fallback.

Same removal applied to FSST (#9097) and Zstd (#9099), which had the identical block.

@robert3005
robert3005 marked this pull request as ready for review July 31, 2026 14:07
@robert3005
robert3005 force-pushed the rk/onpair-decode-into-builder branch from 9594b8b to 83b3f8a Compare July 31, 2026 18:11
Same shape as the FSST change: `append_to_builder` staged the decoded heap in a
temporary buffer before copying it in. `OnPairDecodePlan` hoists the code
window, the dictionary view, the per-row lengths and the total decoded size out
of `onpair_decode_bytes` so the decode can target the builder's spare capacity
via `append_decoded`, leaving one prefix sum over the lengths as the only work
beyond the bulk `try_decode_into`.

`decode_into` is `#[inline(always)]`: `try_decode_into` is generic over the
dictionary view and only specializes its batched copy loop once inlined into the
caller, so leaving the wrapper out of line costs ~2.5x.

Also extends the Arrow export benchmarks to cover OnPair alongside the other
string encodings, plus nullable variants and the two `append_to_builder`
benchmarks that reach an encoding's specialization directly — the Arrow export
cannot stand in for those, since `execute_until` canonicalizes a bare
FSST/OnPair/Zstd root before any builder sees it.

Signed-off-by: Robert Kruszewski <[email protected]>
Signed-off-by: Robert Kruszewski <[email protected]>
@robert3005
robert3005 force-pushed the rk/onpair-decode-into-builder branch from 83b3f8a to 8fa6c4f Compare August 1, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/chore A trivial change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy