Skip to content

fix(parquet): support mask filtering across skipped pages#10288

Merged
alamb merged 6 commits into
apache:mainfrom
hhhizzz:fix/parquet-mask-sparse-pages
Jul 20, 2026
Merged

fix(parquet): support mask filtering across skipped pages#10288
alamb merged 6 commits into
apache:mainfrom
hhhizzz:fix/parquet-mask-sparse-pages

Conversation

@hhhizzz

@hhhizzz hhhizzz commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Mask-backed row selection decodes every row covered by a mask chunk before applying Arrow's filter kernel. Page pruning can leave sparse in-memory column chunks where complete pages were never fetched. If a mask chunk crosses one of those gaps, decoding requests data that is not present and fails with an invalid sparse-page offset.

Previously, Auto avoided this failure by falling back to selectors when page pruning was detected, while an explicit RowSelectionPolicy::Mask could still fail. This PR makes skipped pages safe for Mask execution, allowing explicit Mask to work and Auto to retain its density-based strategy choice.

What changes are included in this PR?

The reader now computes LoadedRowRanges: absolute row-group intervals whose backing pages are loaded for every Parquet leaf in the current projection.

For each predicate projection and the final output projection, it:

  1. Maps the pages selected for each projected leaf to absolute row ranges.
  2. Intersects those ranges across the projected leaves.
  3. Gives the resulting ranges to Mask execution.
  4. Ends each decoded mask chunk at a loaded-range boundary.
  5. Uses skip_records() to cross gaps without decoding missing pages.

These ranges are decoder safety boundaries, not output batch boundaries. ParquetRecordBatchReader accumulates multiple safe chunks and their mask bits until it reaches batch_size, then consumes and filters once. Sparse pages therefore do not fragment one logical batch into one batch per loaded range.

When no projected pages were skipped, LoadedRowRanges is omitted and the existing Mask fast path is unchanged. No masks are intersected or rewritten; the original selection mask is still applied by Arrow's filter kernel.

Loaded row range example

Consider two projected columns with different page boundaries and the selection mask 100000000001:

Row partition[0, 4)[4, 6)[6, 8)[8, 10)[10, 12)
Selection mask100000000001
Column A pagesloaded A0not loaded A1 [4, 8)loaded A2 [8, 12)
Column B pagesloaded B0 [0, 6)not loaded B1 [6, 10)loaded B2
LoadedRowRangesloadedunloaded gaploaded
Column A:        [0, 4) U [8, 12)
Column B:        [0, 6) U [10, 12)
LoadedRowRanges: [0, 4) U [10, 12)

The intersection does not need to match any one column's page boundaries. It is a row-domain guarantee: every row in the result has backing page data in every projected leaf. For example, [0, 4) is a valid subset of Column B's [0, 6) page.

Mask execution and batch behavior

With batch_size = 12, the reader processes the example as follows:

Cursor positionDecoder actionSelected rows accumulated
0Read [0, 4) with mask 10001
4skip_records(7) to row 11, then read [11, 12) with mask 12
EndConsume once and apply the combined maskone 2-row batch

The unloaded gap is never decoded, while the loaded-range boundary remains invisible to callers as a batch boundary.

Are these changes tested?

Coverage includes:

  • page-to-row-range conversion and intersections across different column page boundaries;
  • explicit Mask and Auto, with predicate caching enabled and disabled;
  • reads with and without an initial row selection;
  • multiple predicates with projection-specific loaded ranges;
  • sparse loaded ranges coalescing to the requested logical batch size;
  • nested List<Struct<...>> projections whose leaves have different page boundaries;
  • masks trimmed before the end of their enclosing loaded range.

Validated with:

cargo test -p parquet --lib --features arrow
cargo test -p parquet --test arrow_reader --features async

The current GitHub CI run is green, including Parquet tests, Clippy, MSRV, macOS, Windows, wasm32, and PySpark integration.

Are there any user-facing changes?

There are no public API or source compatibility changes.

Explicit Mask execution no longer fails when page pruning creates sparse column data. Auto no longer falls back to selectors solely because pages were pruned, and sparse loaded ranges no longer fragment logical output batches. These changes can affect execution performance characteristics, but not output semantics.

@github-actions github-actions Bot added the parquet Changes to the parquet crate label Jul 5, 2026
@hhhizzz
hhhizzz marked this pull request as draft July 5, 2026 15:43
@hhhizzz hhhizzz changed the title fix(parquet): preserve explicit mask with sparse pages [WIP] fix(parquet): preserve explicit mask with sparse pages Jul 5, 2026
@hhhizzz
hhhizzz marked this pull request as ready for review July 9, 2026 16:38
@hhhizzz hhhizzz changed the title [WIP] fix(parquet): preserve explicit mask with sparse pages fix(parquet): preserve explicit mask with sparse pages Jul 10, 2026
@hhhizzz

hhhizzz commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@alamb 👋Hi, This PR is now ready for review and updated with the latest main.
It fully fixes the sparse-page Mask failure without falling back to selectors. Also tests on my machine. All 1,679 Parquet tests and clippy pass, and SF10 TPC-DS completed without failures or performance regression ✅
When you have time, I’d appreciate a review of the overall approach 🙏😊

@alamb

alamb commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Ok, thank ou @hhhizzz -- I will try. It just takes me a qhile to review non trivial PRs like this (not just the code, but also the approach).

@hhhizzz

hhhizzz commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Ok, thank ou @hhhizzz -- I will try. It just takes me a qhile to review non trivial PRs like this (not just the code, but also the approach).

Thanks, and no rush at all. Please take whatever time works for you. I completely understand that reviewing the overall approach of a non-trivial change takes significantly more time than just reviewing the code.

I’ve been focusing on this area recently, and I added a few diagrams to the PR description in the hope that they make the design and execution flow easier to understand.
I’d also be very interested in taking on more maintenance responsibility in this area over time, so I’d be happy to receive any feedback on the design, implementation, tests, or how I can contribute more effectively.
I’ll try to stay involved in related community discussions and reviews, and provide code suggestions where useful. Please feel free to tag me on related issues or PRs whenever I can help.
Thanks again!

@hhhizzz
hhhizzz marked this pull request as draft July 16, 2026 14:33
@hhhizzz hhhizzz changed the title fix(parquet): preserve explicit mask with sparse pages [WIP] fix(parquet): preserve explicit mask with sparse pages Jul 16, 2026
@hhhizzz
hhhizzz force-pushed the fix/parquet-mask-sparse-pages branch from fd2a99e to 4fef178 Compare July 16, 2026 14:38
hhhizzz added 2 commits July 16, 2026 23:16
Accumulate loaded-range-safe mask chunks until batch_size so sparse page pruning does not fragment logical batches or predicate evaluation. Cover cache policies, initial selections, multiple predicates, and nested columns with different page boundaries.
@hhhizzz hhhizzz changed the title [WIP] fix(parquet): preserve explicit mask with sparse pages fix(parquet): support mask filtering across skipped pages Jul 17, 2026
@hhhizzz
hhhizzz marked this pull request as ready for review July 17, 2026 02:00
@hhhizzz

hhhizzz commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

@alamb 👋 A brief update since your last note: I simplified the implementation
and added the remaining regression coverage for batch shape and nested columns
with different page boundaries.

I also realized that, in earlier iterations, I let the scope grow by pursuing
too many detailed performance improvements at once. AI-assisted tools make it
easy to explore and implement related ideas quickly, but they do not reduce the
reviewer's cognitive load. That scope was therefore asking too much from
reviewers.

I have now narrowed this PR to one behavioral goal: making Mask execution
correct across sparse pages without falling back to selectors. Future
optimizations can be evaluated and reviewed separately in focused follow-up
PRs. This is also how I plan to scope my contributions going forward: establish
the behavioral change first, then optimize incrementally with separate evidence.

The PR has 604 additions and 168 deletions overall, but when #[cfg(test)]
code is counted as tests, the core runtime change is +244/-116 across four
files, or a net increase of 128 lines.
Tests are +360/-52 and account for most
of the net growth. I also revised the description around the LoadedRowRanges
invariant and how safe decode chunks are coalesced into one logical batch.
All current CI checks are green ✅

Whenever your schedule allows, I’d really appreciate your review of the
approach 🙏 I’d like to keep building context in Parquet predicate pushdown
and gradually help maintain this area, including reviewing related issues and
PRs and taking follow-up work. Please feel free to tag me wherever I can be
useful. Thank you! 😊

@alamb

alamb commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

I am really sorry -- I will do this one first thing tomorrow morning

@alamb

alamb commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Whenever your schedule allows, I’d really appreciate your review of the
approach 🙏 I’d like to keep building context in Parquet predicate pushdown
and gradually help maintain this area, including reviewing related issues and
PRs and taking follow-up work. Please feel free to tag me wherever I can be
useful. Thank you! 😊

Thank you very much for this offer -- as you can tell we sorely need more reviewers for this code (which is

One I think that looks particularly promising and quite related is this one by @haohuaijin ; Perhaps you can find some time to help with that

@alamb

alamb commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

AI-assisted tools make it
easy to explore and implement related ideas quickly, but they do not reduce the
reviewer's cognitive load.

I agree with this. As you have seen the bandwidth we have to review code in this repo is quite limited (the same I think applies to pretty much every open source project). Thus, while it is unfortunate, expending extra effort as a contributor to make the changes easy to review is often the best way to get a contribution reviewed sooner

I have now narrowed this PR to one behavioral goal: making Mask execution
correct across sparse pages without falling back to selectors.

Thank you

Future
optimizations can be evaluated and reviewed separately in focused follow-up
PRs. This is also how I plan to scope my contributions going forward: establish
the behavioral change first, then optimize incrementally with separate evidence.

I agree this will hopefully improve the velocity at which we can review and merge your PRs

@alamb

alamb commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

I have begun my review, but have had to spend more time on a release this morning than I had planned

@hhhizzz

hhhizzz commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

I have begun my review, but have had to spend more time on a release this morning than I had planned

Thank you! At the same time I'm also working on reviewing #10141

@alamb

alamb commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

run benchmark arrow_reader arrow_reader_row_filter

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5015574272-1155-tqtd2 6.12.85+ #1 SMP Mon May 11 08:17:35 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing fix/parquet-mask-sparse-pages (152d581) to 980667f (merge-base) diff
BENCH_NAME=arrow_reader
BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench arrow_reader
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5015574272-1156-jnfhs 6.12.85+ #1 SMP Mon May 11 08:17:35 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing fix/parquet-mask-sparse-pages (152d581) to 980667f (merge-base) diff
BENCH_NAME=arrow_reader_row_filter
BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench arrow_reader_row_filter
BENCH_FILTER=
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                                                              fix_parquet-mask-sparse-pages          main
-----                                                                                              -----------------------------          ----
arrow_reader_row_filter/float64 <= 99.0/all_columns/async                                          1.01      5.5±0.02ms        ? ?/sec    1.00      5.4±0.02ms        ? ?/sec
arrow_reader_row_filter/float64 <= 99.0/all_columns/sync                                           1.01      5.3±0.03ms        ? ?/sec    1.00      5.3±0.03ms        ? ?/sec
arrow_reader_row_filter/float64 <= 99.0/exclude_filter_column/async                                1.01      4.7±0.02ms        ? ?/sec    1.00      4.7±0.02ms        ? ?/sec
arrow_reader_row_filter/float64 <= 99.0/exclude_filter_column/sync                                 1.01      4.6±0.02ms        ? ?/sec    1.00      4.6±0.01ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0 AND ts >= 9000/all_columns/async                            1.04      4.3±0.04ms        ? ?/sec    1.00      4.1±0.01ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0 AND ts >= 9000/all_columns/sync                             1.03      4.5±0.05ms        ? ?/sec    1.00      4.4±0.02ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0 AND ts >= 9000/exclude_filter_column/async                  1.01      3.7±0.04ms        ? ?/sec    1.00      3.7±0.01ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0 AND ts >= 9000/exclude_filter_column/sync                   1.02      3.7±0.03ms        ? ?/sec    1.00      3.6±0.01ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0/all_columns/async                                           1.00      5.4±0.02ms        ? ?/sec    1.00      5.4±0.02ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0/all_columns/sync                                            1.00      5.4±0.03ms        ? ?/sec    1.00      5.4±0.03ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0/exclude_filter_column/async                                 1.00      4.7±0.02ms        ? ?/sec    1.00      4.7±0.03ms        ? ?/sec
arrow_reader_row_filter/float64 > 99.0/exclude_filter_column/sync                                  1.00      4.6±0.02ms        ? ?/sec    1.00      4.6±0.02ms        ? ?/sec
arrow_reader_row_filter/int64 == 9999/all_columns/async                                            1.00    891.2±4.26µs        ? ?/sec    1.00    888.3±2.55µs        ? ?/sec
arrow_reader_row_filter/int64 == 9999/all_columns/sync                                             1.01      2.2±0.02ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
arrow_reader_row_filter/int64 == 9999/exclude_filter_column/async                                  1.00    804.8±1.80µs        ? ?/sec    1.00    808.6±1.97µs        ? ?/sec
arrow_reader_row_filter/int64 == 9999/exclude_filter_column/sync                                   1.00      2.1±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
arrow_reader_row_filter/int64 > 90/all_columns/async                                               1.01      7.7±0.04ms        ? ?/sec    1.00      7.6±0.04ms        ? ?/sec
arrow_reader_row_filter/int64 > 90/all_columns/sync                                                1.00      6.8±0.03ms        ? ?/sec    1.00      6.8±0.03ms        ? ?/sec
arrow_reader_row_filter/int64 > 90/exclude_filter_column/async                                     1.01      7.1±0.03ms        ? ?/sec    1.00      7.1±0.03ms        ? ?/sec
arrow_reader_row_filter/int64 > 90/exclude_filter_column/sync                                      1.01      6.3±0.03ms        ? ?/sec    1.00      6.3±0.04ms        ? ?/sec
arrow_reader_row_filter/ts < 9000/all_columns/async                                                1.02      5.1±0.04ms        ? ?/sec    1.00      5.0±0.02ms        ? ?/sec
arrow_reader_row_filter/ts < 9000/all_columns/sync                                                 1.01      5.4±0.03ms        ? ?/sec    1.00      5.3±0.02ms        ? ?/sec
arrow_reader_row_filter/ts < 9000/exclude_filter_column/async                                      1.01      4.6±0.03ms        ? ?/sec    1.00      4.6±0.02ms        ? ?/sec
arrow_reader_row_filter/ts < 9000/exclude_filter_column/sync                                       1.01      4.6±0.04ms        ? ?/sec    1.00      4.6±0.02ms        ? ?/sec
arrow_reader_row_filter/ts >= 9000/all_columns/async                                               1.02      3.5±0.01ms        ? ?/sec    1.00      3.5±0.02ms        ? ?/sec
arrow_reader_row_filter/ts >= 9000/all_columns/sync                                                1.01      3.6±0.02ms        ? ?/sec    1.00      3.6±0.02ms        ? ?/sec
arrow_reader_row_filter/ts >= 9000/exclude_filter_column/async                                     1.01      3.2±0.02ms        ? ?/sec    1.00      3.2±0.02ms        ? ?/sec
arrow_reader_row_filter/ts >= 9000/exclude_filter_column/sync                                      1.00      3.2±0.02ms        ? ?/sec    1.00      3.2±0.01ms        ? ?/sec
arrow_reader_row_filter/utf8View <> ''/all_columns/async                                           1.02      8.6±0.07ms        ? ?/sec    1.00      8.5±0.02ms        ? ?/sec
arrow_reader_row_filter/utf8View <> ''/all_columns/sync                                            1.02      9.4±0.07ms        ? ?/sec    1.00      9.2±0.02ms        ? ?/sec
arrow_reader_row_filter/utf8View <> ''/exclude_filter_column/async                                 1.02      7.2±0.06ms        ? ?/sec    1.00      7.0±0.02ms        ? ?/sec
arrow_reader_row_filter/utf8View <> ''/exclude_filter_column/sync                                  1.01      6.4±0.05ms        ? ?/sec    1.00      6.3±0.02ms        ? ?/sec
arrow_reader_row_filter_limit/float64 <= 99.0/all_columns/limit10/async                            1.00    342.2±1.44µs        ? ?/sec    1.01    344.6±0.60µs        ? ?/sec
arrow_reader_row_filter_limit/float64 <= 99.0/exclude_filter_column/limit10/async                  1.00    332.9±1.28µs        ? ?/sec    1.01    337.6±1.00µs        ? ?/sec
arrow_reader_row_filter_limit/float64 > 99.0 AND ts >= 9000/all_columns/limit10/async              1.00    379.0±1.39µs        ? ?/sec    1.02    385.0±2.06µs        ? ?/sec
arrow_reader_row_filter_limit/float64 > 99.0 AND ts >= 9000/exclude_filter_column/limit10/async    1.00    363.2±1.73µs        ? ?/sec    1.01    366.0±1.24µs        ? ?/sec
arrow_reader_row_filter_limit/float64 > 99.0/all_columns/limit10/async                             1.00    341.5±1.59µs        ? ?/sec    1.01    344.8±0.80µs        ? ?/sec
arrow_reader_row_filter_limit/float64 > 99.0/exclude_filter_column/limit10/async                   1.00    333.6±1.44µs        ? ?/sec    1.01    338.2±0.72µs        ? ?/sec
arrow_reader_row_filter_limit/int64 > 90/all_columns/limit10/async                                 1.00    337.1±1.40µs        ? ?/sec    1.00    338.1±0.92µs        ? ?/sec
arrow_reader_row_filter_limit/int64 > 90/exclude_filter_column/limit10/async                       1.00    330.3±1.46µs        ? ?/sec    1.01    333.2±0.65µs        ? ?/sec
arrow_reader_row_filter_limit/ts < 9000/all_columns/limit10/async                                  1.00    333.4±1.22µs        ? ?/sec    1.00    334.7±1.34µs        ? ?/sec
arrow_reader_row_filter_limit/ts < 9000/exclude_filter_column/limit10/async                        1.00    329.6±1.46µs        ? ?/sec    1.00    329.5±0.71µs        ? ?/sec
arrow_reader_row_filter_limit/ts >= 9000/all_columns/limit10/async                                 1.00    348.7±1.42µs        ? ?/sec    1.01    351.6±0.77µs        ? ?/sec
arrow_reader_row_filter_limit/ts >= 9000/exclude_filter_column/limit10/async                       1.00    341.5±1.60µs        ? ?/sec    1.00    343.1±1.02µs        ? ?/sec
arrow_reader_row_filter_limit/utf8View <> ''/all_columns/limit10/async                             1.00    362.0±1.20µs        ? ?/sec    1.00    361.9±0.84µs        ? ?/sec
arrow_reader_row_filter_limit/utf8View <> ''/exclude_filter_column/limit10/async                   1.00    352.7±0.88µs        ? ?/sec    1.00    353.7±1.88µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 470.1s
Peak memory 45.5 MiB
Avg memory 30.5 MiB
CPU user 467.3s
CPU sys 0.0s
Peak spill 0 B

branch

Metric Value
Wall time 470.1s
Peak memory 45.6 MiB
Avg memory 30.7 MiB
CPU user 465.5s
CPU sys 0.1s
Peak spill 0 B

File an issue against this benchmark runner

@hhhizzz

hhhizzz commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

I also run the TPCDS on my machine, the result is around same, this change only fix some rare situation that using mask on pruned page which shouldn't impact the performance.

@alamb alamb 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.

Thank you @hhhizzz -- I spent quite a while studying this PR and I found it very well structured and a very clever design

In order to merge it, I think we need a few more tests to cover some edge cases (I left specific comments)

I also think it would help a lot to document some of the very clean, though complex design of RowSelectionCursor and MaskCursor (I left some specific suggestions inline as well), though I think we could do this as a follow onn

Comment thread parquet/src/arrow/arrow_reader/mod.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/mod.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/selection.rs Outdated
Comment thread parquet/src/arrow/push_decoder/reader_builder/mod.rs
Comment thread parquet/src/arrow/arrow_reader/mod.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/mod.rs Outdated
@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                                                                      fix_parquet-mask-sparse-pages          main
-----                                                                                                      -----------------------------          ----
arrow_array_reader/BYTE_ARRAY/Decimal128Array/plain encoded, mandatory, no NULLs                           1.00   834.7±10.31µs        ? ?/sec    1.00    837.9±4.71µs        ? ?/sec
arrow_array_reader/BYTE_ARRAY/Decimal128Array/plain encoded, optional, half NULLs                          1.00    940.2±5.38µs        ? ?/sec    1.01    948.5±3.78µs        ? ?/sec
arrow_array_reader/BYTE_ARRAY/Decimal128Array/plain encoded, optional, no NULLs                            1.00    840.6±9.52µs        ? ?/sec    1.00    841.1±8.74µs        ? ?/sec
arrow_array_reader/BinaryArray/dictionary encoded, mandatory, no NULLs                                     1.00    283.7±0.20µs        ? ?/sec    1.00    283.3±0.31µs        ? ?/sec
arrow_array_reader/BinaryArray/dictionary encoded, optional, half NULLs                                    1.00    381.1±0.95µs        ? ?/sec    1.02    388.2±1.12µs        ? ?/sec
arrow_array_reader/BinaryArray/dictionary encoded, optional, no NULLs                                      1.00    281.7±0.34µs        ? ?/sec    1.02    287.9±0.25µs        ? ?/sec
arrow_array_reader/BinaryArray/plain encoded, mandatory, no NULLs                                          1.01    402.3±6.01µs        ? ?/sec    1.00    398.7±5.37µs        ? ?/sec
arrow_array_reader/BinaryArray/plain encoded, optional, half NULLs                                         1.00    458.7±4.35µs        ? ?/sec    1.01    462.3±3.13µs        ? ?/sec
arrow_array_reader/BinaryArray/plain encoded, optional, no NULLs                                           1.00    406.2±4.85µs        ? ?/sec    1.01    411.8±5.72µs        ? ?/sec
arrow_array_reader/BinaryViewArray/dictionary encoded, mandatory, no NULLs                                 1.00     80.4±0.07µs        ? ?/sec    1.00     80.1±0.06µs        ? ?/sec
arrow_array_reader/BinaryViewArray/dictionary encoded, optional, half NULLs                                1.01    112.5±0.17µs        ? ?/sec    1.00    111.5±0.15µs        ? ?/sec
arrow_array_reader/BinaryViewArray/dictionary encoded, optional, no NULLs                                  1.00     84.0±0.05µs        ? ?/sec    1.00     83.8±0.05µs        ? ?/sec
arrow_array_reader/BinaryViewArray/plain encoded, mandatory, no NULLs                                      1.00    145.7±0.83µs        ? ?/sec    1.07    156.2±9.05µs        ? ?/sec
arrow_array_reader/BinaryViewArray/plain encoded, mandatory, no NULLs, short string                        1.00    141.3±0.55µs        ? ?/sec    1.08    152.0±1.67µs        ? ?/sec
arrow_array_reader/BinaryViewArray/plain encoded, optional, half NULLs                                     1.00    149.7±0.56µs        ? ?/sec    1.00    149.7±1.21µs        ? ?/sec
arrow_array_reader/BinaryViewArray/plain encoded, optional, no NULLs                                       1.03    155.5±7.64µs        ? ?/sec    1.00    150.3±0.36µs        ? ?/sec
arrow_array_reader/BooleanArray/plain encoded, mandatory, no NULLs                                         1.00    227.6±0.97µs        ? ?/sec    1.00    227.2±0.85µs        ? ?/sec
arrow_array_reader/BooleanArray/plain encoded, optional, half NULLs                                        1.00    236.1±2.31µs        ? ?/sec    1.01    237.3±1.93µs        ? ?/sec
arrow_array_reader/BooleanArray/plain encoded, optional, no NULLs                                          1.00    231.6±1.26µs        ? ?/sec    1.00    232.2±1.12µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/byte_stream_split encoded, mandatory, no NULLs     1.11  1086.9±11.18µs        ? ?/sec    1.00   982.3±42.24µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/byte_stream_split encoded, optional, half NULLs    1.00    669.4±0.46µs        ? ?/sec    1.00    670.4±1.27µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/byte_stream_split encoded, optional, no NULLs      1.00    969.5±0.62µs        ? ?/sec    1.00    969.9±1.76µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/plain encoded, mandatory, no NULLs                 1.00    188.7±0.45µs        ? ?/sec    1.00    188.6±1.06µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/plain encoded, optional, half NULLs                1.00    293.2±0.73µs        ? ?/sec    1.00    293.9±0.59µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Decimal128Array/plain encoded, optional, no NULLs                  1.01    197.2±0.77µs        ? ?/sec    1.00    194.3±0.64µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/byte_stream_split encoded, mandatory, no NULLs        1.00    129.1±0.23µs        ? ?/sec    1.02    131.9±0.32µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/byte_stream_split encoded, optional, half NULLs       1.00    182.2±0.24µs        ? ?/sec    1.02    185.6±0.45µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/byte_stream_split encoded, optional, no NULLs         1.00    133.1±0.33µs        ? ?/sec    1.02    136.4±1.25µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/plain encoded, mandatory, no NULLs                    1.00     60.2±0.11µs        ? ?/sec    1.01     60.9±0.09µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/plain encoded, optional, half NULLs                   1.00    146.0±0.09µs        ? ?/sec    1.02    148.5±0.57µs        ? ?/sec
arrow_array_reader/FIXED_LEN_BYTE_ARRAY/Float16Array/plain encoded, optional, no NULLs                     1.00     62.9±0.09µs        ? ?/sec    1.01     63.9±0.18µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/byte_stream_split encoded, mandatory, no NULLs                    1.00    801.8±0.82µs        ? ?/sec    1.00    801.8±0.73µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/byte_stream_split encoded, optional, half NULLs                   1.00    509.4±0.96µs        ? ?/sec    1.00    508.9±0.27µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/byte_stream_split encoded, optional, no NULLs                     1.00    805.4±0.75µs        ? ?/sec    1.00    806.8±0.75µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/plain encoded, mandatory, no NULLs                                1.00     23.2±0.11µs        ? ?/sec    1.02     23.6±0.07µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/plain encoded, optional, half NULLs                               1.00    130.8±0.51µs        ? ?/sec    1.00    131.3±0.40µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(16)/plain encoded, optional, no NULLs                                 1.00     26.8±0.08µs        ? ?/sec    1.00     26.9±0.07µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/byte_stream_split encoded, mandatory, no NULLs                     1.00     74.2±0.90µs        ? ?/sec    1.00     74.3±0.18µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/byte_stream_split encoded, optional, half NULLs                    1.00    128.2±0.28µs        ? ?/sec    1.01    129.3±0.14µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/byte_stream_split encoded, optional, no NULLs                      1.00     78.8±0.78µs        ? ?/sec    1.01     79.6±0.63µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/plain encoded, mandatory, no NULLs                                 1.01      5.4±0.03µs        ? ?/sec    1.00      5.3±0.02µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/plain encoded, optional, half NULLs                                1.00     92.4±0.11µs        ? ?/sec    1.01     93.3±0.08µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(2)/plain encoded, optional, no NULLs                                  1.00      8.9±0.03µs        ? ?/sec    1.01      9.0±0.02µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/byte_stream_split encoded, mandatory, no NULLs                     1.11   164.5±10.22µs        ? ?/sec    1.00    148.8±0.35µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/byte_stream_split encoded, optional, half NULLs                    1.00    197.4±0.43µs        ? ?/sec    1.01    199.6±0.20µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/byte_stream_split encoded, optional, no NULLs                      1.00    154.3±0.64µs        ? ?/sec    1.00    155.0±0.42µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/plain encoded, mandatory, no NULLs                                 1.01      7.7±0.04µs        ? ?/sec    1.00      7.6±0.03µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/plain encoded, optional, half NULLs                                1.00    127.7±0.33µs        ? ?/sec    1.00    128.3±0.22µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(4)/plain encoded, optional, no NULLs                                  1.00     11.0±0.03µs        ? ?/sec    1.01     11.1±0.04µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/byte_stream_split encoded, mandatory, no NULLs                     1.01    304.3±1.33µs        ? ?/sec    1.00    300.1±1.10µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/byte_stream_split encoded, optional, half NULLs                    1.00    267.5±0.52µs        ? ?/sec    1.00    266.9±0.68µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/byte_stream_split encoded, optional, no NULLs                      1.12   347.1±29.15µs        ? ?/sec    1.00    309.5±0.99µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/plain encoded, mandatory, no NULLs                                 1.00     12.0±0.04µs        ? ?/sec    1.02     12.2±0.03µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/plain encoded, optional, half NULLs                                1.00    123.5±0.15µs        ? ?/sec    1.01    124.5±0.36µs        ? ?/sec
arrow_array_reader/FixedLenByteArray(8)/plain encoded, optional, no NULLs                                  1.00     15.6±0.05µs        ? ?/sec    1.02     15.9±0.04µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed increasing value                                    1.00     87.3±0.63µs        ? ?/sec    1.01     87.8±0.69µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed single value                                        1.00     78.7±0.44µs        ? ?/sec    1.02     80.0±0.80µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip increasing value                               1.00     50.6±0.31µs        ? ?/sec    1.00     50.8±0.27µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip single value                                   1.00     46.0±0.23µs        ? ?/sec    1.00     46.2±0.37µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip stepped increasing value                       1.00     73.9±0.11µs        ? ?/sec    1.00     74.0±0.09µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip, mandatory, no NULLs                           1.00     88.0±0.41µs        ? ?/sec    1.00     88.2±0.33µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip, optional, half NULLs                          1.00     89.0±0.15µs        ? ?/sec    1.00     89.0±0.19µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed skip, optional, no NULLs                            1.00     89.8±0.39µs        ? ?/sec    1.00     90.1±0.32µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed stepped increasing value                            1.00    106.7±0.16µs        ? ?/sec    1.00    107.0±0.13µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed, mandatory, no NULLs                                1.00    123.9±0.78µs        ? ?/sec    1.00    124.3±0.79µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed, optional, half NULLs                               1.00    146.4±0.36µs        ? ?/sec    1.00    146.1±0.34µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/binary packed, optional, no NULLs                                 1.00    127.2±0.76µs        ? ?/sec    1.00    127.3±0.81µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/byte_stream_split encoded, mandatory, no NULLs                    1.00     54.2±0.09µs        ? ?/sec    1.02     55.0±0.23µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/byte_stream_split encoded, optional, half NULLs                   1.00    110.7±0.37µs        ? ?/sec    1.00    110.5±0.34µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/byte_stream_split encoded, optional, no NULLs                     1.00     57.8±0.09µs        ? ?/sec    1.00     57.5±0.15µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/dictionary encoded, mandatory, no NULLs                           1.01     85.2±0.16µs        ? ?/sec    1.00     84.2±0.07µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/dictionary encoded, optional, half NULLs                          1.01    128.7±0.18µs        ? ?/sec    1.00    127.4±0.13µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/dictionary encoded, optional, no NULLs                            1.02     89.2±0.22µs        ? ?/sec    1.00     87.8±0.08µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/plain encoded, mandatory, no NULLs                                1.02     48.5±0.09µs        ? ?/sec    1.00     47.7±0.05µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/plain encoded, optional, half NULLs                               1.00    108.4±0.15µs        ? ?/sec    1.00    108.0±0.17µs        ? ?/sec
arrow_array_reader/INT32/Decimal128Array/plain encoded, optional, no NULLs                                 1.00     50.5±0.04µs        ? ?/sec    1.00     50.7±0.27µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed increasing value                                    1.00     78.8±0.26µs        ? ?/sec    1.00     78.8±0.14µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed single value                                        1.00     75.1±0.13µs        ? ?/sec    1.00     75.2±0.10µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip increasing value                               1.00     43.8±0.10µs        ? ?/sec    1.01     44.3±0.13µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip single value                                   1.00     42.0±0.10µs        ? ?/sec    1.00     42.1±0.05µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip stepped increasing value                       1.00     67.9±0.18µs        ? ?/sec    1.00     67.7±0.07µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip, mandatory, no NULLs                           1.00     79.8±0.27µs        ? ?/sec    1.00     80.0±0.15µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip, optional, half NULLs                          1.00     90.2±0.14µs        ? ?/sec    1.00     90.2±0.11µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed skip, optional, no NULLs                            1.00     82.1±0.23µs        ? ?/sec    1.00     82.0±0.10µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed stepped increasing value                            1.00    100.1±0.10µs        ? ?/sec    1.00     99.8±0.16µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed, mandatory, no NULLs                                1.00    114.5±0.27µs        ? ?/sec    1.00    114.8±0.21µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed, optional, half NULLs                               1.00    151.8±0.53µs        ? ?/sec    1.00    152.1±0.18µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/binary packed, optional, no NULLs                                 1.00    118.3±0.37µs        ? ?/sec    1.00    118.4±0.17µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/byte_stream_split encoded, mandatory, no NULLs                    1.01     84.0±0.35µs        ? ?/sec    1.00     83.3±0.07µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/byte_stream_split encoded, optional, half NULLs                   1.00    135.9±0.40µs        ? ?/sec    1.00    135.9±0.38µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/byte_stream_split encoded, optional, no NULLs                     1.00     87.2±0.18µs        ? ?/sec    1.00     87.5±0.31µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/dictionary encoded, mandatory, no NULLs                           1.00     87.3±0.19µs        ? ?/sec    1.01     87.7±0.11µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/dictionary encoded, optional, half NULLs                          1.00    139.6±0.16µs        ? ?/sec    1.00    139.9±0.21µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/dictionary encoded, optional, no NULLs                            1.00     91.1±0.10µs        ? ?/sec    1.00     90.7±0.15µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/plain encoded, mandatory, no NULLs                                1.00     54.1±0.13µs        ? ?/sec    1.01     54.7±0.50µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/plain encoded, optional, half NULLs                               1.00    121.3±0.39µs        ? ?/sec    1.00    121.0±0.10µs        ? ?/sec
arrow_array_reader/INT64/Decimal128Array/plain encoded, optional, no NULLs                                 1.01     58.3±0.17µs        ? ?/sec    1.00     57.9±0.09µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed increasing value                                               1.01     54.2±0.74µs        ? ?/sec    1.00     53.8±0.64µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed single value                                                   1.01     45.5±0.55µs        ? ?/sec    1.00     45.3±0.46µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip increasing value                                          1.00     33.7±0.29µs        ? ?/sec    1.00     33.6±0.32µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip single value                                              1.00     28.9±0.29µs        ? ?/sec    1.00     28.8±0.25µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip stepped increasing value                                  1.00     56.8±0.08µs        ? ?/sec    1.00     57.0±0.06µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip, mandatory, no NULLs                                      1.00     71.0±0.25µs        ? ?/sec    1.00     70.8±0.29µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip, optional, half NULLs                                     1.00     71.9±0.15µs        ? ?/sec    1.00     71.6±0.20µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed skip, optional, no NULLs                                       1.00     72.9±0.25µs        ? ?/sec    1.00     72.8±0.29µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed stepped increasing value                                       1.00     73.6±0.12µs        ? ?/sec    1.00     73.5±0.15µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed, mandatory, no NULLs                                           1.00     90.1±0.77µs        ? ?/sec    1.00     90.2±0.68µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed, optional, half NULLs                                          1.01    113.0±0.30µs        ? ?/sec    1.00    111.9±0.37µs        ? ?/sec
arrow_array_reader/Int16Array/binary packed, optional, no NULLs                                            1.00     93.9±0.65µs        ? ?/sec    1.00     93.8±0.71µs        ? ?/sec
arrow_array_reader/Int16Array/byte_stream_split encoded, mandatory, no NULLs                               1.00     21.1±0.05µs        ? ?/sec    1.00     21.2±0.04µs        ? ?/sec
arrow_array_reader/Int16Array/byte_stream_split encoded, optional, half NULLs                              1.01     77.5±0.09µs        ? ?/sec    1.00     76.9±0.14µs        ? ?/sec
arrow_array_reader/Int16Array/byte_stream_split encoded, optional, no NULLs                                1.00     24.8±0.07µs        ? ?/sec    1.00     24.8±0.04µs        ? ?/sec
arrow_array_reader/Int16Array/dictionary encoded, mandatory, no NULLs                                      1.01     52.1±0.05µs        ? ?/sec    1.00     51.4±0.08µs        ? ?/sec
arrow_array_reader/Int16Array/dictionary encoded, optional, half NULLs                                     1.01     95.3±0.18µs        ? ?/sec    1.00     94.5±0.09µs        ? ?/sec
arrow_array_reader/Int16Array/dictionary encoded, optional, no NULLs                                       1.01     55.9±0.07µs        ? ?/sec    1.00     55.3±0.04µs        ? ?/sec
arrow_array_reader/Int16Array/plain encoded, mandatory, no NULLs                                           1.00     14.0±0.05µs        ? ?/sec    1.00     14.0±0.04µs        ? ?/sec
arrow_array_reader/Int16Array/plain encoded, optional, half NULLs                                          1.00     74.6±0.09µs        ? ?/sec    1.00     75.0±0.12µs        ? ?/sec
arrow_array_reader/Int16Array/plain encoded, optional, no NULLs                                            1.00     17.9±0.03µs        ? ?/sec    1.00     17.9±0.03µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed increasing value                                               1.01     50.6±0.72µs        ? ?/sec    1.00     50.1±0.53µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed single value                                                   1.00     42.5±0.55µs        ? ?/sec    1.00     42.3±0.57µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip increasing value                                          1.01     31.8±0.31µs        ? ?/sec    1.00     31.6±0.27µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip single value                                              1.00     27.2±0.28µs        ? ?/sec    1.00     27.3±0.31µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip stepped increasing value                                  1.00     55.1±0.11µs        ? ?/sec    1.00     55.2±0.06µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip, mandatory, no NULLs                                      1.00     69.0±0.40µs        ? ?/sec    1.00     69.0±0.32µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip, optional, half NULLs                                     1.00     70.5±0.17µs        ? ?/sec    1.00     70.5±0.17µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed skip, optional, no NULLs                                       1.00     71.1±0.37µs        ? ?/sec    1.00     71.1±0.31µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed stepped increasing value                                       1.01     70.3±0.61µs        ? ?/sec    1.00     69.8±0.15µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed, mandatory, no NULLs                                           1.02     88.2±0.82µs        ? ?/sec    1.00     86.8±0.66µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed, optional, half NULLs                                          1.01    110.8±0.38µs        ? ?/sec    1.00    110.2±0.30µs        ? ?/sec
arrow_array_reader/Int32Array/binary packed, optional, no NULLs                                            1.01     91.8±0.93µs        ? ?/sec    1.00     91.0±0.68µs        ? ?/sec
arrow_array_reader/Int32Array/byte_stream_split encoded, mandatory, no NULLs                               1.00     17.4±0.03µs        ? ?/sec    1.00     17.4±0.03µs        ? ?/sec
arrow_array_reader/Int32Array/byte_stream_split encoded, optional, half NULLs                              1.01     74.8±0.15µs        ? ?/sec    1.00     74.3±0.12µs        ? ?/sec
arrow_array_reader/Int32Array/byte_stream_split encoded, optional, no NULLs                                1.01     21.2±0.05µs        ? ?/sec    1.00     21.0±0.02µs        ? ?/sec
arrow_array_reader/Int32Array/dictionary encoded, mandatory, no NULLs                                      1.02     48.6±0.06µs        ? ?/sec    1.00     47.5±0.05µs        ? ?/sec
arrow_array_reader/Int32Array/dictionary encoded, optional, half NULLs                                     1.00     91.4±0.13µs        ? ?/sec    1.00     91.2±0.09µs        ? ?/sec
arrow_array_reader/Int32Array/dictionary encoded, optional, no NULLs                                       1.02     52.3±0.06µs        ? ?/sec    1.00     51.3±0.06µs        ? ?/sec
arrow_array_reader/Int32Array/plain encoded, mandatory, no NULLs                                           1.00     10.2±0.04µs        ? ?/sec    1.00     10.1±0.04µs        ? ?/sec
arrow_array_reader/Int32Array/plain encoded, optional, half NULLs                                          1.01     71.7±0.12µs        ? ?/sec    1.00     71.2±0.08µs        ? ?/sec
arrow_array_reader/Int32Array/plain encoded, optional, no NULLs                                            1.00     13.7±0.04µs        ? ?/sec    1.00     13.7±0.03µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed increasing value                                               1.01     41.7±0.12µs        ? ?/sec    1.00     41.3±0.11µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed single value                                                   1.01     38.7±0.11µs        ? ?/sec    1.00     38.1±0.08µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip increasing value                                          1.01     25.0±0.08µs        ? ?/sec    1.00     24.8±0.09µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip single value                                              1.00     23.2±0.05µs        ? ?/sec    1.00     23.1±0.04µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip stepped increasing value                                  1.00     48.6±0.05µs        ? ?/sec    1.00     48.6±0.06µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip, mandatory, no NULLs                                      1.00     61.0±0.20µs        ? ?/sec    1.00     60.9±0.07µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip, optional, half NULLs                                     1.00     70.9±0.09µs        ? ?/sec    1.00     71.1±0.07µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed skip, optional, no NULLs                                       1.00     63.1±0.16µs        ? ?/sec    1.00     63.1±0.06µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed stepped increasing value                                       1.00     62.8±0.12µs        ? ?/sec    1.00     62.9±0.11µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed, mandatory, no NULLs                                           1.00     77.6±0.15µs        ? ?/sec    1.00     77.4±0.14µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed, optional, half NULLs                                          1.00    114.6±0.15µs        ? ?/sec    1.00    114.7±0.15µs        ? ?/sec
arrow_array_reader/Int64Array/binary packed, optional, no NULLs                                            1.00     81.4±0.14µs        ? ?/sec    1.00     81.4±0.14µs        ? ?/sec
arrow_array_reader/Int64Array/byte_stream_split encoded, mandatory, no NULLs                               1.00     45.7±0.06µs        ? ?/sec    1.01     46.2±0.08µs        ? ?/sec
arrow_array_reader/Int64Array/byte_stream_split encoded, optional, half NULLs                              1.01     99.1±0.24µs        ? ?/sec    1.00     98.6±0.27µs        ? ?/sec
arrow_array_reader/Int64Array/byte_stream_split encoded, optional, no NULLs                                1.00     50.4±0.07µs        ? ?/sec    1.00     50.5±0.07µs        ? ?/sec
arrow_array_reader/Int64Array/dictionary encoded, mandatory, no NULLs                                      1.01     50.7±0.04µs        ? ?/sec    1.00     50.0±0.05µs        ? ?/sec
arrow_array_reader/Int64Array/dictionary encoded, optional, half NULLs                                     1.01    103.1±0.10µs        ? ?/sec    1.00    101.8±0.07µs        ? ?/sec
arrow_array_reader/Int64Array/dictionary encoded, optional, no NULLs                                       1.01     54.2±0.04µs        ? ?/sec    1.00     53.6±0.07µs        ? ?/sec
arrow_array_reader/Int64Array/plain encoded, mandatory, no NULLs                                           1.00     16.4±0.07µs        ? ?/sec    1.00     16.4±0.05µs        ? ?/sec
arrow_array_reader/Int64Array/plain encoded, optional, half NULLs                                          1.00     84.5±0.11µs        ? ?/sec    1.00     84.8±0.20µs        ? ?/sec
arrow_array_reader/Int64Array/plain encoded, optional, no NULLs                                            1.01     20.7±0.07µs        ? ?/sec    1.00     20.4±0.05µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed increasing value                                                1.00     53.8±0.72µs        ? ?/sec    1.01     54.1±0.52µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed single value                                                    1.00     45.2±0.57µs        ? ?/sec    1.01     45.7±0.44µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip increasing value                                           1.00     33.6±0.27µs        ? ?/sec    1.00     33.6±0.32µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip single value                                               1.00     28.7±0.29µs        ? ?/sec    1.01     29.0±0.26µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip stepped increasing value                                   1.00     56.8±0.07µs        ? ?/sec    1.00     56.9±0.05µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip, mandatory, no NULLs                                       1.00     70.4±0.32µs        ? ?/sec    1.00     70.4±0.28µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip, optional, half NULLs                                      1.00     71.5±0.16µs        ? ?/sec    1.00     71.6±0.16µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed skip, optional, no NULLs                                        1.00     72.7±0.31µs        ? ?/sec    1.00     72.5±0.29µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed stepped increasing value                                        1.00     73.4±0.12µs        ? ?/sec    1.00     73.5±0.18µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed, mandatory, no NULLs                                            1.00     89.7±0.60µs        ? ?/sec    1.00     89.3±0.59µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed, optional, half NULLs                                           1.00    112.2±0.30µs        ? ?/sec    1.00    111.8±0.27µs        ? ?/sec
arrow_array_reader/Int8Array/binary packed, optional, no NULLs                                             1.00     93.3±0.60µs        ? ?/sec    1.00     93.3±0.54µs        ? ?/sec
arrow_array_reader/Int8Array/byte_stream_split encoded, mandatory, no NULLs                                1.01     21.1±0.03µs        ? ?/sec    1.00     20.9±0.04µs        ? ?/sec
arrow_array_reader/Int8Array/byte_stream_split encoded, optional, half NULLs                               1.01     77.6±0.16µs        ? ?/sec    1.00     76.5±0.10µs        ? ?/sec
arrow_array_reader/Int8Array/byte_stream_split encoded, optional, no NULLs                                 1.01     24.8±0.10µs        ? ?/sec    1.00     24.5±0.04µs        ? ?/sec
arrow_array_reader/Int8Array/dictionary encoded, mandatory, no NULLs                                       1.01     51.8±0.05µs        ? ?/sec    1.00     51.2±0.04µs        ? ?/sec
arrow_array_reader/Int8Array/dictionary encoded, optional, half NULLs                                      1.01     94.8±0.10µs        ? ?/sec    1.00     94.3±0.10µs        ? ?/sec
arrow_array_reader/Int8Array/dictionary encoded, optional, no NULLs                                        1.02     56.0±0.06µs        ? ?/sec    1.00     55.0±0.08µs        ? ?/sec
arrow_array_reader/Int8Array/plain encoded, mandatory, no NULLs                                            1.00     13.8±0.06µs        ? ?/sec    1.00     13.9±0.06µs        ? ?/sec
arrow_array_reader/Int8Array/plain encoded, optional, half NULLs                                           1.00     74.0±0.10µs        ? ?/sec    1.00     74.2±0.14µs        ? ?/sec
arrow_array_reader/Int8Array/plain encoded, optional, no NULLs                                             1.00     17.5±0.02µs        ? ?/sec    1.01     17.7±0.04µs        ? ?/sec
arrow_array_reader/ListArray/Fixed32List/90pct NULLs                                                       1.00   905.9±13.21µs        ? ?/sec    1.00   909.9±13.07µs        ? ?/sec
arrow_array_reader/ListArray/Fixed32List/99pct NULLs                                                       1.00   462.9±15.82µs        ? ?/sec    1.00   463.9±15.82µs        ? ?/sec
arrow_array_reader/ListArray/Fixed32List/half NULLs                                                        1.00      2.3±0.05ms        ? ?/sec    1.00      2.3±0.05ms        ? ?/sec
arrow_array_reader/ListArray/Fixed32List/no NULLs                                                          1.00      3.1±0.06ms        ? ?/sec    1.04      3.2±0.15ms        ? ?/sec
arrow_array_reader/ListArray/Int32List/90pct NULLs                                                         1.00   897.2±12.82µs        ? ?/sec    1.01   902.7±12.15µs        ? ?/sec
arrow_array_reader/ListArray/Int32List/99pct NULLs                                                         1.00   462.9±15.70µs        ? ?/sec    1.01   467.8±16.01µs        ? ?/sec
arrow_array_reader/ListArray/Int32List/half NULLs                                                          1.00      2.0±0.01ms        ? ?/sec    1.00      2.0±0.01ms        ? ?/sec
arrow_array_reader/ListArray/Int32List/no NULLs                                                            1.00      2.8±0.01ms        ? ?/sec    1.01      2.8±0.02ms        ? ?/sec
arrow_array_reader/ListArray/StringList/90pct NULLs                                                        1.00   955.3±12.92µs        ? ?/sec    1.01   960.9±13.70µs        ? ?/sec
arrow_array_reader/ListArray/StringList/99pct NULLs                                                        1.00   465.8±15.84µs        ? ?/sec    1.01   468.8±15.90µs        ? ?/sec
arrow_array_reader/ListArray/StringList/half NULLs                                                         1.01      3.1±0.05ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
arrow_array_reader/ListArray/StringList/no NULLs                                                           1.05      5.1±0.15ms        ? ?/sec    1.00      4.9±0.02ms        ? ?/sec
arrow_array_reader/StringArray/const delta byte array encoded, mandatory, no NULLs                         1.05    532.7±1.64µs        ? ?/sec    1.00    509.5±2.16µs        ? ?/sec
arrow_array_reader/StringArray/const delta length byte array encoded, mandatory, no NULLs                  1.05    226.0±6.61µs        ? ?/sec    1.00    215.3±2.12µs        ? ?/sec
arrow_array_reader/StringArray/const prefix delta byte array encoded, mandatory, no NULLs                  1.05   804.6±28.32µs        ? ?/sec    1.00   769.3±30.12µs        ? ?/sec
arrow_array_reader/StringArray/dictionary encoded, mandatory, no NULLs                                     1.00    277.4±0.18µs        ? ?/sec    1.00    278.5±0.30µs        ? ?/sec
arrow_array_reader/StringArray/dictionary encoded, optional, half NULLs                                    1.00    379.8±0.64µs        ? ?/sec    1.02    389.0±1.03µs        ? ?/sec
arrow_array_reader/StringArray/dictionary encoded, optional, no NULLs                                      1.00    281.6±0.15µs        ? ?/sec    1.02    287.9±0.57µs        ? ?/sec
arrow_array_reader/StringArray/plain encoded, mandatory, no NULLs                                          1.00    444.2±4.92µs        ? ?/sec    1.01    447.9±6.31µs        ? ?/sec
arrow_array_reader/StringArray/plain encoded, optional, half NULLs                                         1.00    486.1±4.49µs        ? ?/sec    1.01    489.2±3.01µs        ? ?/sec
arrow_array_reader/StringArray/plain encoded, optional, no NULLs                                           1.02    464.1±5.19µs        ? ?/sec    1.00    455.6±7.08µs        ? ?/sec
arrow_array_reader/StringDictionary/dictionary encoded, mandatory, no NULLs                                1.00    248.3±0.56µs        ? ?/sec    1.00    248.9±0.75µs        ? ?/sec
arrow_array_reader/StringDictionary/dictionary encoded, optional, half NULLs                               1.00    263.1±0.70µs        ? ?/sec    1.01    264.8±0.87µs        ? ?/sec
arrow_array_reader/StringDictionary/dictionary encoded, optional, no NULLs                                 1.00    252.1±0.53µs        ? ?/sec    1.00    251.6±0.59µs        ? ?/sec
arrow_array_reader/StringViewArray/dictionary encoded, mandatory, no NULLs                                 1.00     80.6±0.05µs        ? ?/sec    1.00     80.3±0.08µs        ? ?/sec
arrow_array_reader/StringViewArray/dictionary encoded, optional, half NULLs                                1.01    112.1±0.14µs        ? ?/sec    1.00    111.4±0.11µs        ? ?/sec
arrow_array_reader/StringViewArray/dictionary encoded, optional, no NULLs                                  1.01     84.4±0.05µs        ? ?/sec    1.00     83.8±0.08µs        ? ?/sec
arrow_array_reader/StringViewArray/plain encoded, mandatory, no NULLs                                      1.01    223.2±1.26µs        ? ?/sec    1.00    220.9±0.38µs        ? ?/sec
arrow_array_reader/StringViewArray/plain encoded, optional, half NULLs                                     1.02    188.4±1.35µs        ? ?/sec    1.00    185.5±0.39µs        ? ?/sec
arrow_array_reader/StringViewArray/plain encoded, optional, no NULLs                                       1.01    231.1±2.39µs        ? ?/sec    1.00    229.4±0.32µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed increasing value                                              1.00     53.7±0.68µs        ? ?/sec    1.00     53.7±0.58µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed single value                                                  1.00     45.2±0.41µs        ? ?/sec    1.00     45.2±0.45µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip increasing value                                         1.00     33.5±0.27µs        ? ?/sec    1.00     33.5±0.29µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip single value                                             1.00     28.7±0.23µs        ? ?/sec    1.00     28.7±0.24µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip stepped increasing value                                 1.00     56.9±0.09µs        ? ?/sec    1.00     56.8±0.05µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip, mandatory, no NULLs                                     1.01     74.0±0.13µs        ? ?/sec    1.00     73.4±0.14µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip, optional, half NULLs                                    1.00     73.6±0.07µs        ? ?/sec    1.00     73.3±0.11µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed skip, optional, no NULLs                                      1.00     75.7±0.13µs        ? ?/sec    1.00     75.8±0.12µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed stepped increasing value                                      1.00     73.8±0.12µs        ? ?/sec    1.00     73.6±0.14µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed, mandatory, no NULLs                                          1.00     92.9±0.29µs        ? ?/sec    1.00     93.0±0.32µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed, optional, half NULLs                                         1.00    114.6±0.11µs        ? ?/sec    1.00    114.9±0.18µs        ? ?/sec
arrow_array_reader/UInt16Array/binary packed, optional, no NULLs                                           1.00     96.8±0.25µs        ? ?/sec    1.00     96.7±0.24µs        ? ?/sec
arrow_array_reader/UInt16Array/byte_stream_split encoded, mandatory, no NULLs                              1.00     21.1±0.04µs        ? ?/sec    1.00     21.0±0.05µs        ? ?/sec
arrow_array_reader/UInt16Array/byte_stream_split encoded, optional, half NULLs                             1.01     78.1±0.12µs        ? ?/sec    1.00     77.3±0.17µs        ? ?/sec
arrow_array_reader/UInt16Array/byte_stream_split encoded, optional, no NULLs                               1.00     24.9±0.04µs        ? ?/sec    1.00     25.0±0.04µs        ? ?/sec
arrow_array_reader/UInt16Array/dictionary encoded, mandatory, no NULLs                                     1.02     52.3±0.06µs        ? ?/sec    1.00     51.2±0.06µs        ? ?/sec
arrow_array_reader/UInt16Array/dictionary encoded, optional, half NULLs                                    1.02     95.6±0.10µs        ? ?/sec    1.00     94.2±0.11µs        ? ?/sec
arrow_array_reader/UInt16Array/dictionary encoded, optional, no NULLs                                      1.01     56.0±0.05µs        ? ?/sec    1.00     55.3±0.06µs        ? ?/sec
arrow_array_reader/UInt16Array/plain encoded, mandatory, no NULLs                                          1.00     13.9±0.03µs        ? ?/sec    1.01     14.0±0.06µs        ? ?/sec
arrow_array_reader/UInt16Array/plain encoded, optional, half NULLs                                         1.01     74.6±0.14µs        ? ?/sec    1.00     74.2±0.10µs        ? ?/sec
arrow_array_reader/UInt16Array/plain encoded, optional, no NULLs                                           1.00     17.8±0.04µs        ? ?/sec    1.02     18.2±0.06µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed increasing value                                              1.01     50.4±0.59µs        ? ?/sec    1.00     50.0±0.58µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed single value                                                  1.01     42.0±0.39µs        ? ?/sec    1.00     41.7±0.33µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip increasing value                                         1.00     31.8±0.26µs        ? ?/sec    1.00     31.6±0.33µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip single value                                             1.00     27.0±0.21µs        ? ?/sec    1.00     27.0±0.18µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip stepped increasing value                                 1.00     55.3±0.06µs        ? ?/sec    1.00     55.2±0.04µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip, mandatory, no NULLs                                     1.00     69.1±0.37µs        ? ?/sec    1.00     69.3±0.31µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip, optional, half NULLs                                    1.00     70.3±0.15µs        ? ?/sec    1.00     70.5±0.16µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed skip, optional, no NULLs                                      1.00     71.1±0.29µs        ? ?/sec    1.00     71.2±0.33µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed stepped increasing value                                      1.00     70.1±0.15µs        ? ?/sec    1.00     70.3±0.14µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed, mandatory, no NULLs                                          1.00     86.9±0.91µs        ? ?/sec    1.00     86.8±0.75µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed, optional, half NULLs                                         1.00    110.5±0.34µs        ? ?/sec    1.00    110.0±0.36µs        ? ?/sec
arrow_array_reader/UInt32Array/binary packed, optional, no NULLs                                           1.00     90.8±0.85µs        ? ?/sec    1.00     90.6±0.75µs        ? ?/sec
arrow_array_reader/UInt32Array/byte_stream_split encoded, mandatory, no NULLs                              1.00     17.7±0.03µs        ? ?/sec    1.00     17.6±0.03µs        ? ?/sec
arrow_array_reader/UInt32Array/byte_stream_split encoded, optional, half NULLs                             1.01     74.1±0.10µs        ? ?/sec    1.00     73.4±0.07µs        ? ?/sec
arrow_array_reader/UInt32Array/byte_stream_split encoded, optional, no NULLs                               1.01     21.1±0.03µs        ? ?/sec    1.00     20.9±0.06µs        ? ?/sec
arrow_array_reader/UInt32Array/dictionary encoded, mandatory, no NULLs                                     1.02     48.7±0.04µs        ? ?/sec    1.00     47.9±0.05µs        ? ?/sec
arrow_array_reader/UInt32Array/dictionary encoded, optional, half NULLs                                    1.00     92.2±0.11µs        ? ?/sec    1.00     91.8±0.09µs        ? ?/sec
arrow_array_reader/UInt32Array/dictionary encoded, optional, no NULLs                                      1.02     52.4±0.05µs        ? ?/sec    1.00     51.6±0.04µs        ? ?/sec
arrow_array_reader/UInt32Array/plain encoded, mandatory, no NULLs                                          1.00     10.2±0.03µs        ? ?/sec    1.00     10.2±0.04µs        ? ?/sec
arrow_array_reader/UInt32Array/plain encoded, optional, half NULLs                                         1.00     71.5±0.08µs        ? ?/sec    1.01     72.0±0.12µs        ? ?/sec
arrow_array_reader/UInt32Array/plain encoded, optional, no NULLs                                           1.00     14.0±0.03µs        ? ?/sec    1.01     14.1±0.03µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed increasing value                                              1.02     42.3±0.12µs        ? ?/sec    1.00     41.5±0.12µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed single value                                                  1.01     38.8±0.14µs        ? ?/sec    1.00     38.3±0.08µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip increasing value                                         1.01     25.0±0.08µs        ? ?/sec    1.00     24.7±0.09µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip single value                                             1.03     23.5±0.06µs        ? ?/sec    1.00     22.9±0.05µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip stepped increasing value                                 1.00     48.7±0.06µs        ? ?/sec    1.00     48.5±0.07µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip, mandatory, no NULLs                                     1.00     60.9±0.11µs        ? ?/sec    1.00     61.0±0.14µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip, optional, half NULLs                                    1.00     71.3±0.10µs        ? ?/sec    1.00     71.3±0.09µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed skip, optional, no NULLs                                      1.00     62.8±0.09µs        ? ?/sec    1.00     63.1±0.07µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed stepped increasing value                                      1.00     63.0±0.21µs        ? ?/sec    1.00     63.1±0.11µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed, mandatory, no NULLs                                          1.00     77.5±0.13µs        ? ?/sec    1.00     77.8±0.28µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed, optional, half NULLs                                         1.00    115.5±0.18µs        ? ?/sec    1.00    115.1±0.12µs        ? ?/sec
arrow_array_reader/UInt64Array/binary packed, optional, no NULLs                                           1.00     81.5±0.13µs        ? ?/sec    1.00     81.7±0.29µs        ? ?/sec
arrow_array_reader/UInt64Array/byte_stream_split encoded, mandatory, no NULLs                              1.00     46.0±0.20µs        ? ?/sec    1.01     46.3±0.11µs        ? ?/sec
arrow_array_reader/UInt64Array/byte_stream_split encoded, optional, half NULLs                             1.00     99.3±0.27µs        ? ?/sec    1.00     99.0±0.24µs        ? ?/sec
arrow_array_reader/UInt64Array/byte_stream_split encoded, optional, no NULLs                               1.00     50.0±0.18µs        ? ?/sec    1.02     50.9±0.10µs        ? ?/sec
arrow_array_reader/UInt64Array/dictionary encoded, mandatory, no NULLs                                     1.01     50.7±0.05µs        ? ?/sec    1.00     50.1±0.04µs        ? ?/sec
arrow_array_reader/UInt64Array/dictionary encoded, optional, half NULLs                                    1.01    103.4±0.99µs        ? ?/sec    1.00    102.1±0.09µs        ? ?/sec
arrow_array_reader/UInt64Array/dictionary encoded, optional, no NULLs                                      1.01     54.3±0.14µs        ? ?/sec    1.00     53.8±0.08µs        ? ?/sec
arrow_array_reader/UInt64Array/plain encoded, mandatory, no NULLs                                          1.01     16.5±0.02µs        ? ?/sec    1.00     16.4±0.05µs        ? ?/sec
arrow_array_reader/UInt64Array/plain encoded, optional, half NULLs                                         1.00     84.7±0.25µs        ? ?/sec    1.00     84.8±0.07µs        ? ?/sec
arrow_array_reader/UInt64Array/plain encoded, optional, no NULLs                                           1.02     20.6±0.02µs        ? ?/sec    1.00     20.2±0.10µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed increasing value                                               1.01     53.9±0.64µs        ? ?/sec    1.00     53.3±0.60µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed single value                                                   1.02     46.4±0.52µs        ? ?/sec    1.00     45.4±0.49µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip increasing value                                          1.01     33.6±0.33µs        ? ?/sec    1.00     33.3±0.29µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip single value                                              1.02     29.3±0.31µs        ? ?/sec    1.00     28.9±0.24µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip stepped increasing value                                  1.01     57.1±0.08µs        ? ?/sec    1.00     56.8±0.05µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip, mandatory, no NULLs                                      1.00     73.5±0.27µs        ? ?/sec    1.00     73.2±0.19µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip, optional, half NULLs                                     1.00     73.3±0.12µs        ? ?/sec    1.00     73.1±0.11µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed skip, optional, no NULLs                                       1.00     75.6±0.27µs        ? ?/sec    1.00     75.6±0.20µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed stepped increasing value                                       1.01     73.9±0.48µs        ? ?/sec    1.00     73.3±0.21µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed, mandatory, no NULLs                                           1.00     92.9±0.50µs        ? ?/sec    1.00     92.5±0.45µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed, optional, half NULLs                                          1.01    114.0±0.24µs        ? ?/sec    1.00    113.3±0.21µs        ? ?/sec
arrow_array_reader/UInt8Array/binary packed, optional, no NULLs                                            1.00     96.7±0.51µs        ? ?/sec    1.00     96.2±0.45µs        ? ?/sec
arrow_array_reader/UInt8Array/byte_stream_split encoded, mandatory, no NULLs                               1.01     21.1±0.06µs        ? ?/sec    1.00     20.9±0.05µs        ? ?/sec
arrow_array_reader/UInt8Array/byte_stream_split encoded, optional, half NULLs                              1.01     77.3±0.12µs        ? ?/sec    1.00     76.8±0.14µs        ? ?/sec
arrow_array_reader/UInt8Array/byte_stream_split encoded, optional, no NULLs                                1.01     24.8±0.06µs        ? ?/sec    1.00     24.5±0.04µs        ? ?/sec
arrow_array_reader/UInt8Array/dictionary encoded, mandatory, no NULLs                                      1.02     52.2±0.12µs        ? ?/sec    1.00     51.1±0.05µs        ? ?/sec
arrow_array_reader/UInt8Array/dictionary encoded, optional, half NULLs                                     1.01     94.9±0.09µs        ? ?/sec    1.00     94.2±0.09µs        ? ?/sec
arrow_array_reader/UInt8Array/dictionary encoded, optional, no NULLs                                       1.02     56.0±0.13µs        ? ?/sec    1.00     55.1±0.04µs        ? ?/sec
arrow_array_reader/UInt8Array/plain encoded, mandatory, no NULLs                                           1.00     13.7±0.05µs        ? ?/sec    1.00     13.7±0.05µs        ? ?/sec
arrow_array_reader/UInt8Array/plain encoded, optional, half NULLs                                          1.01     74.4±0.12µs        ? ?/sec    1.00     73.6±0.17µs        ? ?/sec
arrow_array_reader/UInt8Array/plain encoded, optional, no NULLs                                            1.00     17.4±0.03µs        ? ?/sec    1.02     17.7±0.05µs        ? ?/sec
arrow_array_reader/struct/Int32Array/plain encoded, mandatory struct, optional data, half NULLs            1.00     71.8±0.11µs        ? ?/sec    1.00     71.6±0.13µs        ? ?/sec
arrow_array_reader/struct/Int32Array/plain encoded, mandatory struct, optional data, no NULLs              1.00     13.9±0.03µs        ? ?/sec    1.00     13.9±0.07µs        ? ?/sec
arrow_array_reader/struct/Int32Array/plain encoded, optional struct, optional data, half NULLs             1.00    131.8±0.14µs        ? ?/sec    1.00    132.1±0.20µs        ? ?/sec
arrow_array_reader/struct/Int32Array/plain encoded, optional struct, optional data, no NULLs               1.01     65.6±0.10µs        ? ?/sec    1.00     65.1±0.06µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 2950.6s
Peak memory 65.3 MiB
Avg memory 23.5 MiB
CPU user 2945.8s
CPU sys 0.5s
Peak spill 0 B

branch

Metric Value
Wall time 2960.6s
Peak memory 65.2 MiB
Avg memory 23.6 MiB
CPU user 2958.1s
CPU sys 0.5s
Peak spill 0 B

File an issue against this benchmark runner

Make the trailing-skip invariant explicit and remove unreachable empty-chunk handling. Extract mask accumulation from next_inner and document how loaded ranges coalesce into one logical batch.
@hhhizzz

hhhizzz commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Thank you @hhhizzz -- I spent quite a while studying this PR and I found it very well structured and a very clever design

In order to merge it, I think we need a few more tests to cover some edge cases (I left specific comments)

I also think it would help a lot to document some of the very clean, though complex design of RowSelectionCursor and MaskCursor (I left some specific suggestions inline as well), though I think we could do this as a follow onn

Thanks for the careful review. I have addressed the coverage and readability points locally: the two unreachable branches are gone, the trailing-skip invariant now has dedicated tests, the Mask path has been extracted from next_inner, and MaskCursor now includes a source-level walkthrough.

I also reran the suggested llvm-cov command. The full parquet test suite passed, and the newly extracted cursor and accumulator paths are covered.

@alamb alamb 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.

Thank you @hhhizzz -- think this looks great. I went through the code and tests again and it is looking 👌

I took the liberty of pushing a commit that has a more fully worked example in comments for FilterMaskAccumulator and merging up from main.

read_plan: ReadPlan,
}

/// Accumulates filter masks for decoded chunks in one logical output batch.

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.

Thank you for this-- I found it much clearer

return Ok(None);
}

let filter_mask = filter_mask

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.

thank you -- this now ready very clearly to me

@alamb

alamb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

I also am running some performance tests:

@alamb

alamb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Performance tests looks good so I'll merge this one in

Thank you again @hhhizzz

@alamb
alamb merged commit 0cc0713 into apache:main Jul 20, 2026
16 checks passed
haohuaijin added a commit to haohuaijin/arrow-rs that referenced this pull request Jul 21, 2026
Resolves conflicts with apache#10288 (mask filtering across skipped pages):
- Port LoadedRowRanges-aware MaskCursor (next_chunk / next_mask_chunk_non_empty)
  into selection/boolean.rs
- Thread loaded_row_ranges into both RowSelectionCursor::new_mask_from_buffer
  and new_mask_from_selectors
- Keep LoadedRowRanges in selection/mod.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Parquet] Support skipping pages with mask based evaluation

3 participants