Skip to content

perf(parquet): avoid redundant copies in mask-backed intersection/union - #10446

Open
haohuaijin wants to merge 10 commits into
apache:mainfrom
haohuaijin:perf-uneven-mask-intersect-union
Open

perf(parquet): avoid redundant copies in mask-backed intersection/union#10446
haohuaijin wants to merge 10 commits into
apache:mainfrom
haohuaijin:perf-uneven-mask-intersect-union

Conversation

@haohuaijin

@haohuaijin haohuaijin commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

The bitwise intersection/union path, taken when both operands are mask-backed, does avoidable copying in two places:

  • Unequal lengths allocate twice — once for the result over the common prefix, then again for a BooleanBufferBuilder that appends that prefix and the longer side's tail.
  • Equal lengths go through BitAnd/BitOr on &BooleanBuffer, which normalise the result to a zero bit offset. That normalisation is a second allocation plus a shifting copy of the whole mask, and it happens whenever from_bitwise_binary_op returns a non-zero offset — i.e. when both operands share a non-zero sub-64-bit alignment.

Masks here come from BooleanBuffer::slice, so a non-zero offset is the ordinary case.

What changes are included in this PR?

Unequal lengths now copy the longer mask once and apply &=/|= in place over the common prefix, leaving the tail where it already is. Equal lengths build the result directly with BooleanBuffer::from_bitwise_binary_op, keeping whatever offset it produces. Both keep the sub-byte offset rather than re-aligning, and consumers are already offset-aware.

Only the longer mask's own byte range is copied, so a result derived from a small slice of a large buffer does not retain the large allocation.

The uneven path is also what motivated #10444 — it reads the bits past the common prefix back out, so it relies on the in-place op leaving them alone.

Are these changes tested?

test_mask_algebra_with_offsets sweeps a 7×7 offset grid against twelve length pairs, equal and unequal; test_mask_algebra_fuzz runs 200 randomized rounds biased towards equal lengths; test_mask_algebra_does_not_retain_backing_buffer covers the allocation-retention case above. All compare against a bit-by-bit reference. cargo test -p parquet --all-features passes (1305 tests); clippy and fmt clean.

This PR also adds mask_intersection/mask_union to parquet/benches/row_selector.rs, since the existing intersection/union benchmarks build operands with from_filters and never reach this path.

CARGO_PROFILE_BENCH_CODEGEN_UNITS=1 cargo bench -p parquet --bench row_selector -- 'mask_intersection|mask_union'

3M rows, ~1/3 density. Rows are the operand length ratio, columns are the (left, right) bit offsets the operands carry. Whether the two offsets agree mod 64 decides which path from_bitwise_binary_op takes, so both are covered.

Speedup (main / this PR), as intersection / union:

(0, 0) (3, 3) (3, 67) (3, 5)
equal 1.00 / 1.09 2.23 / 2.12 2.09 / 2.24 3.55 / 3.26
tail1 1.18 / 1.17 5.90 / 5.96 6.03 / 5.98 5.15 / 4.55
tail1of3 1.22 / 1.21 5.68 / 5.69 5.74 / 5.38 5.03 / 4.30
tail_most 1.49 / 1.51 2.75 / 2.60 2.77 / 2.71 2.63 / 2.69

equal at (0, 0) is the one case with nothing to save: the operands are already aligned, so the old code never paid for normalisation, and old and new produce identical buffers. Its confidence intervals overlap (11.3±0.21µs vs 11.3±0.28µs, 10.0±0.92µs vs 10.9±0.86µs).

codegen-units=1 because the default bench profile is noisy here: the shifting path is sensitive to codegen-unit partitioning, enough to move these numbers by ±10% in either direction.

Are there any user-facing changes?

No public signature changes and no change to which rows a selection selects. The underlying mask layout can differ, though: RowSelection::as_mask() is public, and where equal-length intersection/union previously always returned a zero-offset BooleanBuffer, the result may now carry a non-zero offset, which is observable through values(), inner() and ptr_eq(). as_mask() does not promise a normalised layout and callers must already honour BooleanBuffer::offset(), so this should not be a breaking change.

@github-actions github-actions Bot added parquet Changes to the parquet crate arrow Changes to the arrow crate labels Jul 27, 2026
@haohuaijin
haohuaijin force-pushed the perf-uneven-mask-intersect-union branch from d332086 to 236925a Compare July 27, 2026 04:56
…ual lengths

When two mask-backed `RowSelection`s have different lengths, the bitwise
`intersection`/`union` path allocated twice: once for the bitwise result over
the common prefix, and once more for a `BooleanBufferBuilder` that appended
the prefix and then the longer side's tail, copying both.

Copy the longer mask once into a `MutableBuffer` instead and apply `&=`/`|=`
in place over the common prefix with `bit_util::apply_bitwise_binary_op`. The
tail is already in the right place, so it needs no copy at all.

Neither the mask offsets nor the prefix length are assumed to be byte aligned.
Masks reaching this path may carry a non-zero bit offset from
`BooleanBuffer::slice`, and the prefix may end mid byte. The copy keeps the
longer mask's sub-byte offset rather than re-aligning it, so it stays a plain
byte copy, and that offset is carried over to the returned buffer.

Criterion, mask-backed `RowSelection::intersection`/`union`, ~1/3 density:

                          before      after     change
    intersect 3M / 2M     16.60 us   12.96 us   -21.9%
    union     3M / 2M     16.57 us   13.12 us   -20.8%
    intersect 3M / 3M-1   20.22 us   16.51 us   -18.3%
    union     3M / 3M-1   20.19 us   16.66 us   -17.5%
    intersect 100K / 1K     509 ns     278 ns   -45.4%
    union     100K / 1K     525 ns     270 ns   -48.6%

The gain grows with the tail, which the old code copied through the builder
for no reason.

Tested by an exhaustive sweep over unaligned offset and length combinations
and a randomized fuzz test, both checked against a bit-by-bit reference.

Closes apache#10425
@haohuaijin
haohuaijin force-pushed the perf-uneven-mask-intersect-union branch from 236925a to ab44ada Compare August 4, 2026 02:22
@github-actions github-actions Bot removed the arrow Changes to the arrow crate label Aug 4, 2026
The existing `intersection`/`union` benchmarks build their operands with
`from_filters`, which is selector-backed, so they take the `RowSelector` merge
path and never reach the bitwise one.

Add `mask_intersection`/`mask_union` alongside them, varying two dimensions
that drive the bitwise path: the ratio between operand lengths, since the
longer side's tail passes through unchanged, and the bit offset both operands
carry, since masks come from `BooleanBuffer::slice` and an offset that is not
byte aligned puts the underlying helpers on their shifting path.
@haohuaijin
haohuaijin marked this pull request as ready for review August 4, 2026 13:13
@haohuaijin

haohuaijin commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Hi @alamb @hhhizzz, this PR cuts a redundant copy out of the mask-backed intersection/union path — 19–35% faster on byte-aligned masks, 57–84% when they aren't. Also adds a benchmark, since nothing covered it. ready for reviews — thanks!

…ebra

`BitAnd`/`BitOr` on `&BooleanBuffer` normalise their result to a zero bit
offset. When the operands are not byte aligned, `buffer_bin_and`'s closing
`sliced()` is a second allocation plus a shifting copy of the whole mask, and
that copy dominates the operation.

Build the result with `BooleanBuffer::from_bitwise_binary_op` instead and keep
whatever offset it produces, which is what the uneven-length path already does.
Masks reaching here come from `BooleanBuffer::slice`, so a non-zero offset is
the ordinary case, and consumers are offset-aware.

3M rows, ~1/3 density, `codegen-units=1`:

                                  before     after     change
    intersection equal/aligned    11.36 us   11.25 us   -1.0%
    intersection equal/unaligned  98.45 us   42.31 us  -57.0%
    union equal/aligned           11.23 us   10.56 us   -6.0%
    union equal/unaligned         97.86 us   42.07 us  -57.0%

Aligned operands never paid for the normalisation, so they are unchanged. The
twelve uneven-length cases move within noise.

The equal-length path was previously covered only through `l & r`, so extend
the sweep with six equal-length pairs across the same offset grid and bias the
fuzz test towards equal lengths.
@haohuaijin haohuaijin changed the title perf(parquet): single-allocation intersect_masks/union_masks for unequal lengths perf(parquet): avoid redundant copies in mask-backed intersection/union Aug 4, 2026

@hhhizzz hhhizzz 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! Added some small suggestion.

Comment thread parquet/benches/row_selector.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/selection/algebra.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/selection/algebra.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/selection/algebra.rs Outdated
@haohuaijin

haohuaijin commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

thanks for your reviews @hhhizzz , i apply the suggestion in 5fe3cb7.

this is benchmark result after added the suggestion benchmark
image

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

2 small suggestions.

Comment thread parquet/src/arrow/arrow_reader/selection/algebra.rs Outdated
Comment thread parquet/src/arrow/arrow_reader/selection/algebra.rs Outdated
@hhhizzz

hhhizzz commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

thanks for your reviews @hhhizzz , i apply the suggestion in 5fe3cb7.

this is benchmark result after added the suggestion benchmark

Thanks for providing the full critcmp output. The raw timings look stable, and the equal/both_zero result being flat is a useful sanity check.

The remaining result I find surprising is equal/diff_mod64:

  • intersection: 98.8 µs -> 27.8 µs (3.55x)
  • union: 90.3 µs -> 27.7 µs (3.26x)

With different mod-64 alignments, BooleanBuffer::from_bitwise_binary_op takes the shifting fallback and returns an offset-zero buffer. The old buffer_bin_and / buffer_bin_or wrappers should therefore use into_inner() without performing the additional normalization copy. The new path calls the same underlying helper directly.

So the improvement looks real, but it does not appear to come from the redundant-copy removal described in the PR. Could you clarify whether this is a cross-crate inlining/codegen effect? One useful way to isolate it would be to benchmark &left & &right against a direct from_bitwise_binary_op call on the same commit and with the same inputs.

@haohuaijin

Copy link
Copy Markdown
Contributor Author

So the improvement looks real, but it does not appear to come from the redundant-copy removal described in the PR. Could you clarify whether this is a cross-crate inlining/codegen effect? One useful way to isolate it would be to benchmark &left & &right against a direct from_bitwise_binary_op call on the same commit and with the same inputs.

Thanks for the suggestion — I ran the isolation, then took it further with LTO. All on upstream/main, both variants in one binary, same inputs, codegen-units=1:

offsets variant no LTO fat LTO
(3, 5) &l & &r 97.0 µs 97.3 µs
(3, 5) direct 25.6 µs 97.4 µs

At (3, 5) both produce byte-identical buffers, and the gap disappears under LTO. Thus equal/diff_mod64 is an artifact of cross-crate codegen, not related to this change. (LTO slowing the direct call😂.)

@alamb

alamb commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

run benchmark mask_intersection

@alamb

alamb commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

merging up from main to try and get a clean CI run

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5208866997-1491-98jjq 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 perf-uneven-mask-intersect-union (004bf28) to 3df22cd (merge-base) diff

Run configuration
run benchmark mask_intersection

BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench mask_intersection
Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

Benchmark for this request failed.

Run configuration
run benchmark mask_intersection

Last 20 lines of output:

Click to expand
    regexp_kernels
    row_format
    row_group_index_reader
    row_selection_cursor
    row_selector
    row_selector_boolean_buffer
    serde
    sort_kernel
    string_dictionary_builder
    string_run_builder
    string_run_iterator
    substring_kernels
    take_kernels
    union_array
    variant_builder
    variant_kernels
    variant_validation
    view_types
    writer_overhead
    zip_kernels

File an issue against this benchmark runner

@alamb

alamb commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

run benchmark row_selector

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5208939378-1492-rjxhc 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 perf-uneven-mask-intersect-union (004bf28) to 3df22cd (merge-base) diff

Run configuration
run benchmark row_selector

BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench row_selector
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)

Comparing perf-uneven-mask-intersect-union (004bf28) to 3df22cd (merge-base) diff

Run configuration
run benchmark row_selector
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                                         main                                   perf-uneven-mask-intersect-union
-----                                         ----                                   --------------------------------
and_then                                      1.02    604.2±2.69µs        ? ?/sec    1.00    592.2±2.99µs        ? ?/sec
from_filters                                  1.00    369.0±3.46µs        ? ?/sec    1.01    371.7±4.56µs        ? ?/sec
intersection                                  1.03   1338.0±2.50µs        ? ?/sec    1.00   1305.1±2.62µs        ? ?/sec
mask_consume/random                           1.00    352.2±2.29µs        ? ?/sec    1.16    408.6±2.48µs        ? ?/sec
mask_consume/run01                            1.00    684.9±4.13µs        ? ?/sec    1.14   777.9±27.37µs        ? ?/sec
mask_consume/run04                            1.00   166.9±14.77µs        ? ?/sec    1.07   178.4±11.89µs        ? ?/sec
mask_consume/run128                           1.07      8.5±0.02µs        ? ?/sec    1.00      7.9±0.13µs        ? ?/sec
mask_consume/run16                            1.00     44.9±5.07µs        ? ?/sec    1.03     46.0±4.98µs        ? ?/sec
mask_consume/run32                            1.02     22.8±1.82µs        ? ?/sec    1.00     22.5±1.92µs        ? ?/sec
mask_consume/run48                            1.03     16.3±1.00µs        ? ?/sec    1.00     15.8±0.95µs        ? ?/sec
mask_consume/run64                            1.01     13.0±0.28µs        ? ?/sec    1.00     12.9±0.45µs        ? ?/sec
mask_consume/run96                            1.05      9.5±0.03µs        ? ?/sec    1.00      9.0±0.03µs        ? ?/sec
mask_intersection/equal/both_zero                                                    1.00      9.1±0.05µs        ? ?/sec
mask_intersection/equal/diff_mod64                                                   1.00     44.9±0.11µs        ? ?/sec
mask_intersection/equal/same_mod64                                                   1.00     47.8±1.05µs        ? ?/sec
mask_intersection/equal/same_mod64_far                                               1.00     47.8±0.15µs        ? ?/sec
mask_intersection/tail1/both_zero                                                    1.00     18.9±0.03µs        ? ?/sec
mask_intersection/tail1/diff_mod64                                                   1.00     34.4±0.04µs        ? ?/sec
mask_intersection/tail1/same_mod64                                                   1.00     24.1±0.04µs        ? ?/sec
mask_intersection/tail1/same_mod64_far                                               1.00     24.1±0.03µs        ? ?/sec
mask_intersection/tail1of3/both_zero                                                 1.00     14.2±0.02µs        ? ?/sec
mask_intersection/tail1of3/diff_mod64                                                1.00     24.4±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64                                                1.00     17.4±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64_far                                            1.00     17.6±0.74µs        ? ?/sec
mask_intersection/tail_most/both_zero                                                1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/diff_mod64                                               1.00      5.2±0.01µs        ? ?/sec
mask_intersection/tail_most/same_mod64                                               1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/same_mod64_far                                           1.00      5.2±0.01µs        ? ?/sec
mask_iterate_then_consume/random              1.00    389.0±2.38µs        ? ?/sec    1.17    456.0±2.56µs        ? ?/sec
mask_iterate_then_consume/run01               1.00   783.6±15.31µs        ? ?/sec    1.14   896.5±29.69µs        ? ?/sec
mask_iterate_then_consume/run04               1.00   184.8±15.56µs        ? ?/sec    1.07   196.8±11.18µs        ? ?/sec
mask_iterate_then_consume/run128              1.07      9.0±0.03µs        ? ?/sec    1.00      8.4±0.12µs        ? ?/sec
mask_iterate_then_consume/run16               1.00     48.6±5.11µs        ? ?/sec    1.01     49.1±4.60µs        ? ?/sec
mask_iterate_then_consume/run32               1.02     24.7±1.95µs        ? ?/sec    1.00     24.1±1.77µs        ? ?/sec
mask_iterate_then_consume/run48               1.03     17.5±1.03µs        ? ?/sec    1.00     17.0±0.93µs        ? ?/sec
mask_iterate_then_consume/run64               1.03     14.1±0.33µs        ? ?/sec    1.00     13.7±0.26µs        ? ?/sec
mask_iterate_then_consume/run96               1.05     10.1±0.02µs        ? ?/sec    1.00      9.6±0.11µs        ? ?/sec
mask_union/equal/both_zero                                                           1.00      9.2±0.03µs        ? ?/sec
mask_union/equal/diff_mod64                                                          1.00     41.9±0.05µs        ? ?/sec
mask_union/equal/same_mod64                                                          1.00     48.5±3.90µs        ? ?/sec
mask_union/equal/same_mod64_far                                                      1.00     47.8±0.14µs        ? ?/sec
mask_union/tail1/both_zero                                                           1.00     18.9±0.03µs        ? ?/sec
mask_union/tail1/diff_mod64                                                          1.00     33.2±1.25µs        ? ?/sec
mask_union/tail1/same_mod64                                                          1.00     24.0±0.06µs        ? ?/sec
mask_union/tail1/same_mod64_far                                                      1.00     24.1±0.03µs        ? ?/sec
mask_union/tail1of3/both_zero                                                        1.00     14.1±0.03µs        ? ?/sec
mask_union/tail1of3/diff_mod64                                                       1.00     23.5±0.03µs        ? ?/sec
mask_union/tail1of3/same_mod64                                                       1.00     17.3±0.02µs        ? ?/sec
mask_union/tail1of3/same_mod64_far                                                   1.00     17.5±0.02µs        ? ?/sec
mask_union/tail_most/both_zero                                                       1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/diff_mod64                                                      1.00      5.2±0.02µs        ? ?/sec
mask_union/tail_most/same_mod64                                                      1.00      5.2±0.01µs        ? ?/sec
mask_union/tail_most/same_mod64_far                                                  1.00      5.2±0.01µs        ? ?/sec
union                                         1.08   1420.0±2.45µs        ? ?/sec    1.00   1314.8±1.72µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 235.1s
Peak memory 14.6 MiB
Avg memory 13.7 MiB
CPU user 230.0s
CPU sys 0.0s
Peak spill 0 B

branch

Metric Value
Wall time 535.1s
Peak memory 16.9 MiB
Avg memory 15.5 MiB
CPU user 532.6s
CPU sys 0.1s
Peak spill 0 B

File an issue against this benchmark runner

@haohuaijin

haohuaijin commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

split the benchmark to #10574 for easy compare in ci, cc @alamb

alamb pushed a commit that referenced this pull request Aug 7, 2026
…10574)

# Which issue does this PR close?

Split out of #10446 so that CI can compare both sides — the benchmark is
new there, so the merge-base has nothing to compare against and the
`main` column comes out empty.

# Rationale for this change

`row_selector.rs` already benchmarks `intersection`/`union`, but it
builds the operands with `from_filters`, which is selector-backed. Those
take the `RowSelector` merge path and never reach the bitwise one used
when both operands are mask-backed.

# What changes are included in this PR?

Adds `mask_intersection`/`mask_union`, varying the two dimensions that
drive the bitwise path:

- the ratio between operand lengths, since unequal lengths pass the
longer side's tail through unchanged
- the bit offsets the operands carry, since masks come from
`BooleanBuffer::slice` and whether the two share a sub-64-bit alignment
decides which path the underlying helpers take

Benchmark only, no library changes.

# Are these changes tested?

N/A — this is a benchmark. It builds and runs on `main` as-is.

# Are there any user-facing changes?

No.
@alamb

alamb commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

split the benchmark to #10574 for easy compare in ci, cc @alamb

Thank you -- I merged it in and merged this PR up from main Rerunning tests now

@alamb

alamb commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

run benchmark row_selector

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5218498440-1499-mt2br 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector

BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench row_selector
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)

Comparing perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector
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                                         main                                   perf-uneven-mask-intersect-union
-----                                         ----                                   --------------------------------
and_then                                      1.00    590.2±1.93µs        ? ?/sec    1.01    595.2±2.20µs        ? ?/sec
from_filters                                  1.00    370.3±1.76µs        ? ?/sec    1.00    370.8±1.95µs        ? ?/sec
intersection                                  1.00   1300.6±1.55µs        ? ?/sec    1.00   1301.6±2.29µs        ? ?/sec
mask_consume/random                           1.00    402.2±2.88µs        ? ?/sec    1.00    402.5±3.54µs        ? ?/sec
mask_consume/run01                            1.00   777.0±31.47µs        ? ?/sec    1.01   782.4±26.32µs        ? ?/sec
mask_consume/run04                            1.00   178.5±12.64µs        ? ?/sec    1.00   177.7±11.55µs        ? ?/sec
mask_consume/run128                           1.00      7.9±0.01µs        ? ?/sec    1.11      8.8±0.01µs        ? ?/sec
mask_consume/run16                            1.00     46.1±4.84µs        ? ?/sec    1.00     46.0±4.99µs        ? ?/sec
mask_consume/run32                            1.00     22.4±2.04µs        ? ?/sec    1.00     22.4±1.88µs        ? ?/sec
mask_consume/run48                            1.00     15.5±0.77µs        ? ?/sec    1.04     16.2±0.53µs        ? ?/sec
mask_consume/run64                            1.00     12.6±0.07µs        ? ?/sec    1.04     13.1±0.15µs        ? ?/sec
mask_consume/run96                            1.00      8.8±0.04µs        ? ?/sec    1.11      9.8±0.00µs        ? ?/sec
mask_intersection/equal/both_zero             1.03      9.4±0.01µs        ? ?/sec    1.00      9.1±0.02µs        ? ?/sec
mask_intersection/equal/diff_mod64            2.48    110.1±0.03µs        ? ?/sec    1.00     44.5±0.04µs        ? ?/sec
mask_intersection/equal/same_mod64            1.72     87.0±0.64µs        ? ?/sec    1.00     50.6±0.69µs        ? ?/sec
mask_intersection/equal/same_mod64_far        1.83     86.8±0.43µs        ? ?/sec    1.00     47.5±0.04µs        ? ?/sec
mask_intersection/tail1/both_zero             1.00     17.8±0.12µs        ? ?/sec    1.08     19.3±0.07µs        ? ?/sec
mask_intersection/tail1/diff_mod64            3.47    117.9±0.05µs        ? ?/sec    1.00     34.0±0.04µs        ? ?/sec
mask_intersection/tail1/same_mod64            3.71     87.5±0.11µs        ? ?/sec    1.00     23.6±0.03µs        ? ?/sec
mask_intersection/tail1/same_mod64_far        4.02     95.4±0.45µs        ? ?/sec    1.00     23.7±0.03µs        ? ?/sec
mask_intersection/tail1of3/both_zero          1.01     14.6±0.11µs        ? ?/sec    1.00     14.5±0.02µs        ? ?/sec
mask_intersection/tail1of3/diff_mod64         3.62     88.3±0.05µs        ? ?/sec    1.00     24.4±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64         4.26     74.0±0.85µs        ? ?/sec    1.00     17.4±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64_far     3.89     68.0±0.08µs        ? ?/sec    1.00     17.5±0.02µs        ? ?/sec
mask_intersection/tail_most/both_zero         1.49      7.7±0.16µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/diff_mod64        5.52     28.3±0.02µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_intersection/tail_most/same_mod64        5.54     28.3±0.03µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/same_mod64_far    5.52     28.4±0.10µs        ? ?/sec    1.00      5.1±0.02µs        ? ?/sec
mask_iterate_then_consume/random              1.00    448.1±3.24µs        ? ?/sec    1.00    447.0±3.51µs        ? ?/sec
mask_iterate_then_consume/run01               1.00   863.7±30.50µs        ? ?/sec    1.06   911.7±27.96µs        ? ?/sec
mask_iterate_then_consume/run04               1.00   197.2±12.29µs        ? ?/sec    1.00   196.2±12.28µs        ? ?/sec
mask_iterate_then_consume/run128              1.00      8.4±0.01µs        ? ?/sec    1.10      9.2±0.01µs        ? ?/sec
mask_iterate_then_consume/run16               1.00     49.1±4.52µs        ? ?/sec    1.00     49.1±4.62µs        ? ?/sec
mask_iterate_then_consume/run32               1.00     24.0±1.83µs        ? ?/sec    1.00     24.0±1.74µs        ? ?/sec
mask_iterate_then_consume/run48               1.00     16.6±0.75µs        ? ?/sec    1.04     17.3±0.50µs        ? ?/sec
mask_iterate_then_consume/run64               1.00     13.6±0.08µs        ? ?/sec    1.03     13.9±0.13µs        ? ?/sec
mask_iterate_then_consume/run96               1.00      9.5±0.03µs        ? ?/sec    1.10     10.4±0.00µs        ? ?/sec
mask_union/equal/both_zero                    1.03      9.4±0.01µs        ? ?/sec    1.00      9.1±0.02µs        ? ?/sec
mask_union/equal/diff_mod64                   2.67    110.7±0.05µs        ? ?/sec    1.00     41.5±0.04µs        ? ?/sec
mask_union/equal/same_mod64                   1.67     79.6±0.04µs        ? ?/sec    1.00     47.6±0.04µs        ? ?/sec
mask_union/equal/same_mod64_far               1.68     79.9±0.06µs        ? ?/sec    1.00     47.5±0.03µs        ? ?/sec
mask_union/tail1/both_zero                    1.00     17.9±0.05µs        ? ?/sec    1.07     19.2±0.03µs        ? ?/sec
mask_union/tail1/diff_mod64                   3.62    118.2±0.27µs        ? ?/sec    1.00     32.6±0.15µs        ? ?/sec
mask_union/tail1/same_mod64                   3.69     87.6±0.10µs        ? ?/sec    1.00     23.8±0.02µs        ? ?/sec
mask_union/tail1/same_mod64_far               3.69     87.5±0.11µs        ? ?/sec    1.00     23.7±0.04µs        ? ?/sec
mask_union/tail1of3/both_zero                 1.01     14.6±0.11µs        ? ?/sec    1.00     14.5±0.03µs        ? ?/sec
mask_union/tail1of3/diff_mod64                3.79     88.3±0.06µs        ? ?/sec    1.00     23.3±0.03µs        ? ?/sec
mask_union/tail1of3/same_mod64                3.91     67.6±0.05µs        ? ?/sec    1.00     17.3±0.03µs        ? ?/sec
mask_union/tail1of3/same_mod64_far            3.88     67.8±0.05µs        ? ?/sec    1.00     17.5±0.02µs        ? ?/sec
mask_union/tail_most/both_zero                1.50      7.7±0.16µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/diff_mod64               5.51     28.3±0.02µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_union/tail_most/same_mod64               5.55     28.3±0.03µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/same_mod64_far           5.51     28.3±0.03µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
union                                         1.00   1310.5±1.28µs        ? ?/sec    1.00   1316.4±1.51µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 545.1s
Peak memory 18.7 MiB
Avg memory 16.5 MiB
CPU user 542.4s
CPU sys 0.0s
Peak spill 0 B

branch

Metric Value
Wall time 540.1s
Peak memory 16.9 MiB
Avg memory 15.4 MiB
CPU user 534.6s
CPU sys 0.0s
Peak spill 0 B

File an issue against this benchmark runner

@haohuaijin

Copy link
Copy Markdown
Contributor Author

run benchmark row_selector

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5225185097-1500-gdw9g 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector

BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench row_selector
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)

Comparing perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector
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                                         main                                   perf-uneven-mask-intersect-union
-----                                         ----                                   --------------------------------
and_then                                      1.00    587.5±2.65µs        ? ?/sec    1.00    587.3±2.07µs        ? ?/sec
from_filters                                  1.00    370.8±1.95µs        ? ?/sec    1.00    371.4±2.21µs        ? ?/sec
intersection                                  1.00   1300.9±2.24µs        ? ?/sec    1.00   1296.2±1.31µs        ? ?/sec
mask_consume/random                           1.00    398.1±3.25µs        ? ?/sec    1.02    404.9±5.39µs        ? ?/sec
mask_consume/run01                            1.00   776.4±31.17µs        ? ?/sec    1.01   784.5±29.52µs        ? ?/sec
mask_consume/run04                            1.00   177.6±12.85µs        ? ?/sec    1.04   183.9±14.31µs        ? ?/sec
mask_consume/run128                           1.00      7.9±0.01µs        ? ?/sec    1.41     11.2±5.60µs        ? ?/sec
mask_consume/run16                            1.00     45.8±4.53µs        ? ?/sec    1.07     49.0±6.73µs        ? ?/sec
mask_consume/run32                            1.00     22.2±1.77µs        ? ?/sec    1.08     24.0±3.71µs        ? ?/sec
mask_consume/run48                            1.00     15.4±0.75µs        ? ?/sec    1.18     18.2±4.71µs        ? ?/sec
mask_consume/run64                            1.00     12.7±0.08µs        ? ?/sec    1.24     15.7±6.14µs        ? ?/sec
mask_consume/run96                            1.00      8.8±0.04µs        ? ?/sec    1.40     12.3±5.87µs        ? ?/sec
mask_intersection/equal/both_zero             1.00      9.0±0.02µs        ? ?/sec    1.03      9.2±0.02µs        ? ?/sec
mask_intersection/equal/diff_mod64            2.47    110.2±0.04µs        ? ?/sec    1.00     44.6±0.16µs        ? ?/sec
mask_intersection/equal/same_mod64            1.68     79.5±0.08µs        ? ?/sec    1.00     47.4±0.03µs        ? ?/sec
mask_intersection/equal/same_mod64_far        1.82     86.3±0.72µs        ? ?/sec    1.00     47.5±0.02µs        ? ?/sec
mask_intersection/tail1/both_zero             1.00     18.0±0.10µs        ? ?/sec    1.03     18.6±0.02µs        ? ?/sec
mask_intersection/tail1/diff_mod64            3.48    118.2±0.15µs        ? ?/sec    1.00     33.9±0.02µs        ? ?/sec
mask_intersection/tail1/same_mod64            3.67     87.3±0.10µs        ? ?/sec    1.00     23.8±0.03µs        ? ?/sec
mask_intersection/tail1/same_mod64_far        3.64     87.1±0.09µs        ? ?/sec    1.00     23.9±0.09µs        ? ?/sec
mask_intersection/tail1of3/both_zero          1.03     14.5±0.07µs        ? ?/sec    1.00     14.1±0.02µs        ? ?/sec
mask_intersection/tail1of3/diff_mod64         3.64     88.4±0.07µs        ? ?/sec    1.00     24.3±0.01µs        ? ?/sec
mask_intersection/tail1of3/same_mod64         4.13     71.5±3.62µs        ? ?/sec    1.00     17.3±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64_far     3.88     68.1±0.05µs        ? ?/sec    1.00     17.6±0.02µs        ? ?/sec
mask_intersection/tail_most/both_zero         1.44      7.3±0.01µs        ? ?/sec    1.00      5.0±0.01µs        ? ?/sec
mask_intersection/tail_most/diff_mod64        5.56     28.3±0.02µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/same_mod64        5.56     28.3±0.04µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_intersection/tail_most/same_mod64_far    5.57     28.4±0.08µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_iterate_then_consume/random              1.00    435.4±4.09µs        ? ?/sec    1.01    437.9±3.73µs        ? ?/sec
mask_iterate_then_consume/run01               1.01   867.6±33.58µs        ? ?/sec    1.00   860.2±30.67µs        ? ?/sec
mask_iterate_then_consume/run04               1.00   196.1±12.65µs        ? ?/sec    1.00   196.2±11.89µs        ? ?/sec
mask_iterate_then_consume/run128              1.00      8.4±0.01µs        ? ?/sec    1.10      9.2±0.01µs        ? ?/sec
mask_iterate_then_consume/run16               1.00     49.5±4.91µs        ? ?/sec    1.00     49.6±4.98µs        ? ?/sec
mask_iterate_then_consume/run32               1.01     24.4±2.05µs        ? ?/sec    1.00     24.2±1.91µs        ? ?/sec
mask_iterate_then_consume/run48               1.00     16.7±0.81µs        ? ?/sec    1.04     17.4±0.61µs        ? ?/sec
mask_iterate_then_consume/run64               1.00     13.6±0.09µs        ? ?/sec    1.03     14.0±0.12µs        ? ?/sec
mask_iterate_then_consume/run96               1.00      9.5±0.06µs        ? ?/sec    1.10     10.4±0.01µs        ? ?/sec
mask_union/equal/both_zero                    1.00      9.0±0.02µs        ? ?/sec    1.03      9.3±0.02µs        ? ?/sec
mask_union/equal/diff_mod64                   2.63    110.2±0.07µs        ? ?/sec    1.00     41.9±0.03µs        ? ?/sec
mask_union/equal/same_mod64                   1.67     79.5±0.06µs        ? ?/sec    1.00     47.5±0.04µs        ? ?/sec
mask_union/equal/same_mod64_far               1.65     79.8±0.10µs        ? ?/sec    1.00     48.3±1.57µs        ? ?/sec
mask_union/tail1/both_zero                    1.00     18.0±0.09µs        ? ?/sec    1.03     18.6±0.02µs        ? ?/sec
mask_union/tail1/diff_mod64                   3.63    117.8±0.07µs        ? ?/sec    1.00     32.5±0.10µs        ? ?/sec
mask_union/tail1/same_mod64                   4.05     96.8±0.36µs        ? ?/sec    1.00     23.9±0.02µs        ? ?/sec
mask_union/tail1/same_mod64_far               3.64     87.1±0.12µs        ? ?/sec    1.00     24.0±0.03µs        ? ?/sec
mask_union/tail1of3/both_zero                 1.01     14.3±0.06µs        ? ?/sec    1.00     14.1±0.04µs        ? ?/sec
mask_union/tail1of3/diff_mod64                3.76     88.4±0.10µs        ? ?/sec    1.00     23.5±0.02µs        ? ?/sec
mask_union/tail1of3/same_mod64                3.91     67.5±0.06µs        ? ?/sec    1.00     17.3±0.02µs        ? ?/sec
mask_union/tail1of3/same_mod64_far            4.08     71.4±0.84µs        ? ?/sec    1.00     17.5±0.02µs        ? ?/sec
mask_union/tail_most/both_zero                1.44      7.3±0.03µs        ? ?/sec    1.00      5.0±0.01µs        ? ?/sec
mask_union/tail_most/diff_mod64               5.57     28.3±0.02µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/same_mod64               5.56     28.3±0.04µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/same_mod64_far           5.57     28.4±0.05µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
union                                         1.00   1311.6±1.42µs        ? ?/sec    1.00   1309.2±1.00µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 545.1s
Peak memory 18.7 MiB
Avg memory 16.5 MiB
CPU user 540.4s
CPU sys 0.1s
Peak spill 0 B

branch

Metric Value
Wall time 535.1s
Peak memory 16.9 MiB
Avg memory 15.4 MiB
CPU user 532.6s
CPU sys 0.0s
Peak spill 0 B

File an issue against this benchmark runner

@haohuaijin

Copy link
Copy Markdown
Contributor Author

run benchmark row_selector

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5225311392-1501-72hjv 6.12.85+ #1 SMP Wed Jun 17 20:31:55 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 perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector

BENCH_COMMAND=cargo bench --features=arrow,async,test_common,experimental,object_store --bench row_selector
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)

Comparing perf-uneven-mask-intersect-union (635c740) to 3e6bd62 (merge-base) diff

Run configuration
run benchmark row_selector
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                                         main                                   perf-uneven-mask-intersect-union
-----                                         ----                                   --------------------------------
and_then                                      1.00    590.7±2.57µs        ? ?/sec    1.00    591.6±2.17µs        ? ?/sec
from_filters                                  1.00    371.8±2.05µs        ? ?/sec    1.00    371.0±2.32µs        ? ?/sec
intersection                                  1.00   1300.9±1.89µs        ? ?/sec    1.01   1308.4±3.08µs        ? ?/sec
mask_consume/random                           1.01    404.8±3.35µs        ? ?/sec    1.00    402.6±3.58µs        ? ?/sec
mask_consume/run01                            1.00   775.7±30.89µs        ? ?/sec    1.00   775.7±31.73µs        ? ?/sec
mask_consume/run04                            1.00   177.6±11.94µs        ? ?/sec    1.00   177.0±11.67µs        ? ?/sec
mask_consume/run128                           1.00      7.9±0.01µs        ? ?/sec    1.11      8.7±0.01µs        ? ?/sec
mask_consume/run16                            1.00     45.9±4.52µs        ? ?/sec    1.00     45.9±4.99µs        ? ?/sec
mask_consume/run32                            1.00     22.2±1.77µs        ? ?/sec    1.00     22.3±1.88µs        ? ?/sec
mask_consume/run48                            1.00     15.5±0.70µs        ? ?/sec    1.04     16.1±0.57µs        ? ?/sec
mask_consume/run64                            1.00     12.6±0.07µs        ? ?/sec    1.04     13.1±0.11µs        ? ?/sec
mask_consume/run96                            1.00      8.9±0.06µs        ? ?/sec    1.10      9.8±0.01µs        ? ?/sec
mask_intersection/equal/both_zero             1.05      9.3±0.02µs        ? ?/sec    1.00      8.9±0.01µs        ? ?/sec
mask_intersection/equal/diff_mod64            2.48    110.2±0.07µs        ? ?/sec    1.00     44.5±0.04µs        ? ?/sec
mask_intersection/equal/same_mod64            1.76     83.8±0.60µs        ? ?/sec    1.00     47.6±0.08µs        ? ?/sec
mask_intersection/equal/same_mod64_far        1.55     80.0±0.05µs        ? ?/sec    1.00     51.5±0.35µs        ? ?/sec
mask_intersection/tail1/both_zero             1.01     18.6±0.06µs        ? ?/sec    1.00     18.4±0.01µs        ? ?/sec
mask_intersection/tail1/diff_mod64            3.49    118.0±0.10µs        ? ?/sec    1.00     33.8±0.03µs        ? ?/sec
mask_intersection/tail1/same_mod64            3.70     87.7±0.08µs        ? ?/sec    1.00     23.7±0.03µs        ? ?/sec
mask_intersection/tail1/same_mod64_far        3.72     87.9±0.08µs        ? ?/sec    1.00     23.7±0.05µs        ? ?/sec
mask_intersection/tail1of3/both_zero          1.08     15.0±0.05µs        ? ?/sec    1.00     13.9±0.01µs        ? ?/sec
mask_intersection/tail1of3/diff_mod64         3.66     88.5±0.05µs        ? ?/sec    1.00     24.2±0.02µs        ? ?/sec
mask_intersection/tail1of3/same_mod64         3.90     67.7±0.06µs        ? ?/sec    1.00     17.3±0.03µs        ? ?/sec
mask_intersection/tail1of3/same_mod64_far     3.96     68.2±0.08µs        ? ?/sec    1.00     17.2±0.02µs        ? ?/sec
mask_intersection/tail_most/both_zero         1.50      7.7±0.06µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_intersection/tail_most/diff_mod64        5.58     28.4±0.03µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_intersection/tail_most/same_mod64        5.61     28.5±0.07µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_intersection/tail_most/same_mod64_far    5.48     28.4±0.02µs        ? ?/sec    1.00      5.2±0.01µs        ? ?/sec
mask_iterate_then_consume/random              1.01    441.7±3.59µs        ? ?/sec    1.00    439.5±3.75µs        ? ?/sec
mask_iterate_then_consume/run01               1.00   866.6±31.59µs        ? ?/sec    1.00   867.5±31.38µs        ? ?/sec
mask_iterate_then_consume/run04               1.00   196.5±11.51µs        ? ?/sec    1.00   195.8±12.07µs        ? ?/sec
mask_iterate_then_consume/run128              1.00      8.4±0.01µs        ? ?/sec    1.10      9.2±0.01µs        ? ?/sec
mask_iterate_then_consume/run16               1.00     49.7±4.86µs        ? ?/sec    1.00     49.6±4.99µs        ? ?/sec
mask_iterate_then_consume/run32               1.01     24.4±2.11µs        ? ?/sec    1.00     24.2±1.93µs        ? ?/sec
mask_iterate_then_consume/run48               1.00     16.7±0.81µs        ? ?/sec    1.04     17.4±0.56µs        ? ?/sec
mask_iterate_then_consume/run64               1.00     13.6±0.08µs        ? ?/sec    1.02     13.9±0.15µs        ? ?/sec
mask_iterate_then_consume/run96               1.00      9.5±0.04µs        ? ?/sec    1.10     10.4±0.01µs        ? ?/sec
mask_union/equal/both_zero                    1.05      9.3±0.02µs        ? ?/sec    1.00      8.9±0.01µs        ? ?/sec
mask_union/equal/diff_mod64                   2.66    110.2±0.03µs        ? ?/sec    1.00     41.5±0.02µs        ? ?/sec
mask_union/equal/same_mod64                   1.78     85.0±0.48µs        ? ?/sec    1.00     47.6±0.05µs        ? ?/sec
mask_union/equal/same_mod64_far               1.65     85.4±2.23µs        ? ?/sec    1.00     51.8±0.48µs        ? ?/sec
mask_union/tail1/both_zero                    1.02     18.7±0.04µs        ? ?/sec    1.00     18.4±0.01µs        ? ?/sec
mask_union/tail1/diff_mod64                   3.65    117.9±0.11µs        ? ?/sec    1.00     32.3±0.03µs        ? ?/sec
mask_union/tail1/same_mod64                   3.95     93.9±0.66µs        ? ?/sec    1.00     23.8±0.03µs        ? ?/sec
mask_union/tail1/same_mod64_far               3.70     87.5±0.15µs        ? ?/sec    1.00     23.7±0.04µs        ? ?/sec
mask_union/tail1of3/both_zero                 1.07     15.0±0.05µs        ? ?/sec    1.00     13.9±0.02µs        ? ?/sec
mask_union/tail1of3/diff_mod64                3.84     88.5±0.04µs        ? ?/sec    1.00     23.0±0.01µs        ? ?/sec
mask_union/tail1of3/same_mod64                3.95     68.2±0.18µs        ? ?/sec    1.00     17.3±0.01µs        ? ?/sec
mask_union/tail1of3/same_mod64_far            3.96     68.2±0.08µs        ? ?/sec    1.00     17.2±0.01µs        ? ?/sec
mask_union/tail_most/both_zero                1.50      7.7±0.06µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/diff_mod64               5.58     28.4±0.03µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
mask_union/tail_most/same_mod64               5.59     28.4±0.04µs        ? ?/sec    1.00      5.1±0.01µs        ? ?/sec
mask_union/tail_most/same_mod64_far           5.58     28.4±0.02µs        ? ?/sec    1.00      5.1±0.00µs        ? ?/sec
union                                         1.00   1314.5±1.99µs        ? ?/sec    1.00   1318.5±1.44µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 545.1s
Peak memory 18.7 MiB
Avg memory 16.5 MiB
CPU user 539.4s
CPU sys 0.0s
Peak spill 0 B

branch

Metric Value
Wall time 540.1s
Peak memory 16.9 MiB
Avg memory 15.4 MiB
CPU user 534.6s
CPU sys 0.0s
Peak spill 0 B

File an issue against this benchmark runner

@haohuaijin

haohuaijin commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

the benchmark is basicly match this comment #10446 (comment), and the mask_consume / mask_iterate_then_consume movement looks unrelated, this pr do not touch the related path.

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.

Optimize intersect_masks / union_masks for unequal lengths with in-place bitwise ops

4 participants