perf(parquet): batched DELTA decoding with SIMD bit-unpack#6
Open
jaylisde wants to merge 1 commit into
Open
Conversation
This was referenced Jun 3, 2026
jaylisde
force-pushed
the
perf/delta-decoder-overhaul
branch
6 times, most recently
from
June 4, 2026 03:00
601bfd2 to
a613dd9
Compare
jaylisde
force-pushed
the
perf/delta-decoder-overhaul
branch
from
June 4, 2026 06:42
a613dd9 to
17d32a5
Compare
jaylisde
force-pushed
the
perf/delta-decoder-overhaul
branch
9 times, most recently
from
June 4, 2026 08:22
8deaa51 to
b7e08fa
Compare
Closes the DELTA-vs-PLAIN/DICT scan-CPU gap on TPC-H Q12 left after facebookincubator#17633. DELTA scan CPU was ~4.5x of PLAIN/DICT; after this PR ~1.8x. - DeltaBpDecoder: batched decode with one ColumnVisitor::processRun() per chunk; inline SIMD bit-unpack for whole bit-aligned miniblocks at bit_width 0..32; sparse-buffered path for filtered reads. - ColumnVisitor: new base processRun with SIMD filter subpaths. - DeltaByteArrayDecoder: devirtualize, reuse child RleBpDecoder across pages, replace std::string lastValue_ with raw char buffer. Q12 SF10 (4 drivers, 5-run median): baseline (facebookincubator#17633): 1.02 s wall, 2.76 s lineitem scan CPU this PR: 0.594 s wall, 1.11 s lineitem scan CPU −42% −60%
jaylisde
force-pushed
the
perf/delta-decoder-overhaul
branch
from
June 4, 2026 18:04
b7e08fa to
a99db1e
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.
Summary
Closes the DELTA-vs-PLAIN/DICT scan gap on TPC-H Q12 (DELTA-encoded lineitem) left after facebookincubator#17633. DELTA scan CPU was still ~4.5x of PLAIN/DICT; after this PR it's ~1.8x.
The work covers both DELTA-encoded readers in Velox:
DeltaBpDecoder(used byDELTA_BINARY_PACKEDinteger columns and as a length decoder insideDELTA_LENGTH_BYTE_ARRAY/DELTA_BYTE_ARRAY) andDeltaByteArrayDecoder(string columns). Three layered changes:bit_width0–32.ColumnVisitor::processRun()once per chunk instead of per-rowprocess(), with SIMD filter pushdown for deterministic integer filters.DeltaByteArrayDecodermicro-optimizations: devirtualization, decoder reuse across pages, andstd::string→ raw buffer.PLAIN/DICT path is unchanged within noise.
Performance
TPC-H Q12 SF10,
num_drivers=4 --num_repeats=5 --warmup_after_clear=true, 5-run median:Implementation
1. SIMD Bit-Unpack Kernels
Compile-time dispatch on
bit_width0–32:__uint128_tfunnel-shift (lowers toSHRDon x86_64)2. Batched Decode Fast Path (processRun)
Instead of per-row
visitor.process(), decode an entire miniblock into the output buffer and callvisitor.processRun()once per chunk. Two fast paths inside:processFixedFilter3. Sparse Buffered Path
For filtered reads, decode
kBatch=1024physical values into a stack buffer (≤ 8 KB forint64_t, well within typical thread stack limits), then index into it byrows[k] - batchPhysStart. One sequential decode pass (cache-friendly) turns random row access into simple array indexing.4. DeltaByteArrayDecoder Optimizations
DeltaByteArrayDecoderBase, eliminate vtable dispatch from per-rowreadString()RleBpDecoderusesstd::optional+reset()instead ofmake_uniqueper page (saves 3 heap allocations per page boundary)std::string lastValue_withstd::vector<char>+ length — eliminatesstd::string::_M_replaceoverhead (~6.5% in profiling) from prefix-share encoding