Skip to content

perf(arrow): specialize Boolean filtering - #11732

Open
Rich-T-kid wants to merge 7 commits into
apache:mainfrom
Rich-T-kid:rich-T-kid/coalescer-boolean-take
Open

Rich-T-kid wants to merge 7 commits into
apache:mainfrom
Rich-T-kid:rich-T-kid/coalescer-boolean-take

Conversation

@Rich-T-kid

@Rich-T-kid Rich-T-kid commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Boolean columns currently use GenericInProgressArray, which buffers filtered arrays and concatenates them when the output batch is finished.

What changes are included in this PR?

This adds InProgressBooleanArray. It uses the existing Boolean filter kernel and appends the result directly into value and validity builders, avoiding the final concatenation.

Are these changes tested?

The tests cover sliced and filtered copies, null propagation, and buffer reuse after finish.

Are there any significant user-facing changes?

No.

@github-actions github-actions Bot added arrow-core Core crates related to representing arrow data arrow-kernels Crates that transform arrow data (e.g. compute, cast) labels Oct 20, 2026
@Rich-T-kid
Rich-T-kid force-pushed the rich-T-kid/coalescer-boolean-take branch from ed74f33 to 17548a3 Compare October 20, 2026 02:37
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@github-actions github-actions Bot removed the arrow-core Core crates related to representing arrow data label Oct 20, 2026
@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (17548a3) to 1357f25 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (17548a3) to 1357f25 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.64     33.8±0.23ms        ? ?/sec    1.00     20.6±0.04ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.38      3.0±0.02ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.08    541.7±1.68µs        ? ?/sec    1.00    501.3±1.90µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.09    113.3±0.30µs        ? ?/sec    1.00    104.1±0.15µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.18     46.8±0.20ms        ? ?/sec    1.00     21.5±0.11ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.29      4.6±0.02ms        ? ?/sec    1.00      3.5±0.02ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.05    939.9±1.48µs        ? ?/sec    1.00    892.4±1.34µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.05    203.3±0.28µs        ? ?/sec    1.00    194.2±0.23µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.21     19.3±0.10ms        ? ?/sec    1.00     16.0±0.38ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.17      2.6±0.00ms        ? ?/sec    1.00      2.3±0.03ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.16   1012.0±4.69µs        ? ?/sec    1.00    869.2±4.18µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.08      2.5±0.00ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.21     28.1±0.12ms        ? ?/sec    1.00     23.2±0.22ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.16      4.1±0.01ms        ? ?/sec    1.00      3.6±0.03ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.05   1852.6±9.22µs        ? ?/sec    1.00  1769.2±10.93µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.05      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            4.74     13.8±0.36ms        ? ?/sec    1.00      2.9±0.03ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.30  1585.8±40.04µs        ? ?/sec    1.00   1224.0±7.22µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.13    361.6±3.88µs        ? ?/sec    1.00    320.1±1.01µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.04    239.3±0.62µs        ? ?/sec    1.00    230.1±0.65µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          6.20     20.6±0.38ms        ? ?/sec    1.00      3.3±0.04ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.19      2.5±0.04ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    622.2±5.00µs        ? ?/sec    1.00    579.1±1.95µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.02    433.3±0.88µs        ? ?/sec    1.00    426.3±0.40µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-1hlpf16k-a718e4aa-plqr

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

uname:

Linux bench-c6282042375-3619-sk7zh 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 265.1s
Peak memory 24.0 MiB
Avg memory 13.0 MiB
CPU user 261.8s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 265.1s
Peak memory 25.5 MiB
Avg memory 12.9 MiB
CPU user 260.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@Rich-T-kid
Rich-T-kid marked this pull request as ready for review October 20, 2026 04:30
@Rich-T-kid
Rich-T-kid force-pushed the rich-T-kid/coalescer-boolean-take branch from 17548a3 to f114c3e Compare October 20, 2026 05:30
@Rich-T-kid Rich-T-kid changed the title perf(arrow): specialize Boolean coalescing perf(arrow): specialize Boolean filtering Oct 20, 2026
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

@mbutrovich you may be interested since u have context with #11174

@Rich-T-kid
Rich-T-kid force-pushed the rich-T-kid/coalescer-boolean-take branch from f114c3e to e59a5c0 Compare October 20, 2026 05:43
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (e59a5c0) to 1357f25 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (e59a5c0) to 1357f25 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.64     33.8±0.33ms        ? ?/sec    1.00     20.6±0.05ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.43      3.0±0.02ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.07    539.7±1.72µs        ? ?/sec    1.00    502.5±1.90µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.09    113.1±0.28µs        ? ?/sec    1.00    104.0±0.08µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.19     47.0±0.25ms        ? ?/sec    1.00     21.5±0.08ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.36      4.6±0.02ms        ? ?/sec    1.00      3.3±0.03ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    936.5±1.78µs        ? ?/sec    1.00    887.6±1.31µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.05    203.6±0.55µs        ? ?/sec    1.00    194.0±0.34µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.23     19.5±0.10ms        ? ?/sec    1.00     15.9±0.13ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.21      2.6±0.01ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.22   1031.5±7.57µs        ? ?/sec    1.00    842.8±1.76µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.10      2.5±0.00ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.25     28.3±0.17ms        ? ?/sec    1.00     22.5±0.16ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.17      4.1±0.02ms        ? ?/sec    1.00      3.6±0.02ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.15  1909.5±10.47µs        ? ?/sec    1.00   1665.0±4.67µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.08      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.30     13.5±0.09ms        ? ?/sec    1.00     10.4±0.11ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.27   1560.5±6.80µs        ? ?/sec    1.00   1226.9±6.64µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.12    357.1±0.76µs        ? ?/sec    1.00    319.4±0.58µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.04    239.4±0.20µs        ? ?/sec    1.00    229.3±0.22µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.20     20.1±0.08ms        ? ?/sec    1.00     16.7±0.08ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.19      2.5±0.01ms        ? ?/sec    1.00      2.1±0.00ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    617.6±1.08µs        ? ?/sec    1.00    575.4±1.32µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.03    434.3±0.39µs        ? ?/sec    1.00    421.6±0.28µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-8he663m0-8580e27c-845q

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

uname:

Linux bench-c6284416401-3630-5gff4 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 265.1s
Peak memory 24.2 MiB
Avg memory 13.1 MiB
CPU user 262.7s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 260.1s
Peak memory 18.3 MiB
Avg memory 13.0 MiB
CPU user 257.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@Rich-T-kid
Rich-T-kid force-pushed the rich-T-kid/coalescer-boolean-take branch from e59a5c0 to 43295ad Compare October 20, 2026 13:49
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (0211b4c) to d58a0fc (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (0211b4c) to d58a0fc (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@mbutrovich

Copy link
Copy Markdown
Contributor

@mbutrovich you may be interested since u have context with #11174

I can take a look today.

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (6fcfb9d) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (0211b4c) to d58a0fc (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.63     33.8±0.32ms        ? ?/sec    1.00     20.8±0.16ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.43      3.0±0.02ms        ? ?/sec    1.00      2.1±0.02ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.09    541.5±2.10µs        ? ?/sec    1.00    498.8±1.95µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.09    113.7±0.31µs        ? ?/sec    1.00    104.1±0.22µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.17     46.9±0.19ms        ? ?/sec    1.00     21.6±0.20ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.37      4.6±0.01ms        ? ?/sec    1.00      3.4±0.03ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    941.5±1.47µs        ? ?/sec    1.00    889.5±3.38µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.04    203.0±0.31µs        ? ?/sec    1.00    194.5±0.37µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.22     19.3±0.10ms        ? ?/sec    1.00     15.8±0.07ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.21      2.6±0.00ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.21   1019.9±6.60µs        ? ?/sec    1.00    841.5±2.15µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.10      2.5±0.01ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.24     27.9±0.10ms        ? ?/sec    1.00     22.5±0.09ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.16      4.1±0.01ms        ? ?/sec    1.00      3.6±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.14   1901.1±9.39µs        ? ?/sec    1.00   1673.4±3.75µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.07      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.28     13.6±0.11ms        ? ?/sec    1.00     10.7±0.15ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.26   1558.1±6.26µs        ? ?/sec    1.00  1239.6±11.11µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.12    358.9±0.47µs        ? ?/sec    1.00    320.0±1.47µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.04    238.6±0.23µs        ? ?/sec    1.00    230.1±1.30µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.20     20.3±0.06ms        ? ?/sec    1.00     16.9±0.18ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.17      2.5±0.01ms        ? ?/sec    1.00      2.1±0.02ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    618.5±1.49µs        ? ?/sec    1.00    580.0±2.70µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.02    432.4±0.31µs        ? ?/sec    1.00    423.3±0.64µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-11mn6c6n-356aa77f-x2d6

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

uname:

Linux bench-c6317200573-3720-rlhms 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 265.1s
Peak memory 22.2 MiB
Avg memory 13.0 MiB
CPU user 261.8s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 260.1s
Peak memory 16.4 MiB
Avg memory 13.0 MiB
CPU user 258.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (0211b4c) to d58a0fc (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.64     33.9±0.64ms        ? ?/sec    1.00     20.7±0.07ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.44      3.0±0.04ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.09    542.0±4.15µs        ? ?/sec    1.00    498.3±1.74µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.08    113.2±0.40µs        ? ?/sec    1.00    104.5±0.36µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.19     46.8±0.29ms        ? ?/sec    1.00     21.4±0.05ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.37      4.6±0.02ms        ? ?/sec    1.00      3.3±0.02ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    941.9±8.39µs        ? ?/sec    1.00    887.7±2.22µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.05    203.0±0.28µs        ? ?/sec    1.00    194.0±0.38µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.22     19.3±0.11ms        ? ?/sec    1.00     15.9±0.08ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.20      2.6±0.05ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.14    963.6±6.81µs        ? ?/sec    1.00    844.0±2.48µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.08      2.5±0.05ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.25     28.2±0.53ms        ? ?/sec    1.00     22.6±0.11ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.17      4.1±0.02ms        ? ?/sec    1.00      3.5±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.11   1850.7±6.88µs        ? ?/sec    1.00   1673.9±4.39µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.06      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.31     13.7±0.26ms        ? ?/sec    1.00     10.5±0.10ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.26   1567.5±4.10µs        ? ?/sec    1.00   1241.8±8.25µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.13    359.6±0.82µs        ? ?/sec    1.00    318.9±0.76µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.05    239.9±6.61µs        ? ?/sec    1.00    229.4±0.24µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.19     20.4±0.36ms        ? ?/sec    1.00     17.2±0.29ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.20      2.5±0.05ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    617.6±5.72µs        ? ?/sec    1.00    575.0±1.40µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.03    434.5±0.47µs        ? ?/sec    1.00    421.8±0.30µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-9uvij0h8-355ce73c-4lc9

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

uname:

Linux bench-c6317203006-3721-jr94s 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 23.6 MiB
Avg memory 12.9 MiB
CPU user 263.7s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 260.1s
Peak memory 16.3 MiB
Avg memory 12.9 MiB
CPU user 257.1s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (6fcfb9d) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.63     33.6±0.32ms        ? ?/sec    1.00     20.6±0.06ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.37      3.0±0.02ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.08    540.9±2.31µs        ? ?/sec    1.00    500.3±3.00µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.08    113.0±0.24µs        ? ?/sec    1.00    104.6±0.42µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.19     46.8±0.15ms        ? ?/sec    1.00     21.4±0.05ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.31      4.6±0.01ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    943.4±1.38µs        ? ?/sec    1.00    890.1±1.59µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.04    203.2±0.79µs        ? ?/sec    1.00    196.2±0.21µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.22     19.6±0.16ms        ? ?/sec    1.00     16.0±0.08ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.18      2.6±0.02ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.04    893.7±1.95µs        ? ?/sec    1.00    860.8±4.49µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.06      2.4±0.01ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.23     28.2±0.17ms        ? ?/sec    1.00     23.0±0.12ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.16      4.1±0.01ms        ? ?/sec    1.00      3.5±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.03   1743.7±4.34µs        ? ?/sec    1.00   1691.5±8.00µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.04      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.32     13.8±0.29ms        ? ?/sec    1.00     10.5±0.14ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.26  1562.7±25.73µs        ? ?/sec    1.00  1235.6±13.60µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.12    357.7±2.85µs        ? ?/sec    1.00    319.9±1.60µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.05    240.0±0.37µs        ? ?/sec    1.00    229.3±0.29µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.21     20.4±0.31ms        ? ?/sec    1.00     16.8±0.12ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.22      2.6±0.02ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.08    622.5±4.26µs        ? ?/sec    1.00    575.4±1.59µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.03    432.2±0.47µs        ? ?/sec    1.00    420.1±0.55µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-11mn6c6n-b51db246-rwbz

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

uname:

Linux bench-c6317274695-3722-5p7fg 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 22.5 MiB
Avg memory 13.9 MiB
CPU user 264.7s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 265.1s
Peak memory 23.2 MiB
Avg memory 13.8 MiB
CPU user 259.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

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

Thanks @Rich-T-kid! Removing the concat at the end of each Boolean batch looks like a clear win in the benchmark runs above.

Comment thread arrow-select/src/coalesce/boolean.rs Outdated
Comment thread arrow-select/src/coalesce/boolean.rs Outdated
Comment thread arrow-select/src/coalesce/boolean.rs
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

@mbutrovich asked AI to run some benchmarks these are the results. for context i'm on a macbook m4

Image 10-21-26 at 3 20 PM

we could add a couple if/else branches to handle the specific selectivity ratios but Im not sure if we want to do this. we would able to produce somewhat similar results but we both have macbooks so that may be a factor.

for now ill include it but if it seems wonky id be happy to remove it

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author
  • Source has nulls: per-bit at <= 1/128
  • Source has no nulls: per-bit at <= 1/256
  • Otherwise: use filter.filter()
  • 0.1 and 0.8 always use the kernel;

compared to main (locally)

Image 10-21-26 at 3 40 PM

@mbutrovich

Copy link
Copy Markdown
Contributor

Thanks for the updated numbers @Rich-T-kid. I don't love overspecializing implementation magic numbers on point-in-time benchmarks, unless it's something obvious like word size. Let me step back and think if there's a way to accomplish this without the selectivity heuristic, since that's only one signal on the distribution.

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (4c23338) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (4c23338) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@mbutrovich

Copy link
Copy Markdown
Contributor

What about replacing the per-bit path and both cutoffs with a kernel that filters values and validity straight into the builders, 64 bits at a time?

As I read it, the per-bit path wins because of what it skips, not because appending one bit at a time is cheap. On the kernel path, filter_boolean allocates a filtered values buffer. filter_nulls then scans the whole filter a second time and allocates a null buffer, and append_array copies both into the builders. The per-bit path does none of that, but it pays per selected row: two bit reads and two appends that each branch on the bit. Without nulls, the kernel's extra cost is mostly fixed per batch, so the crossover is a row count rather than a fraction. With nulls, the second scan grows with the batch length. That fits the two cutoffs you found.

Both cutoffs also depend on inputs the benchmark holds fixed:

  • The kernel's cost tracks the 64-bit filter words that contain at least one selected row, not the selected rows. coalesce_kernels draws each filter bit independently, so at 0.001 about 6% of words have a selected row. If the same rows arrive in runs, the kernel runs compress on up to 64x fewer words, while the per-bit path does the same work.
  • compress is a single pext instruction (extract the bits selected by a mask) only when bmi2 is enabled at build time. Default x86_64 builds and all aarch64 builds use the portable fallback, and the bot and my runs are both aarch64. In Faster count_set_bits on aarch64 by summing byte popcounts before widening #11776 the same portable popcount change is 28% faster on aarch64 and about 80% slower on Zen 5 (numbers), so a cutoff measured on one architecture may not carry over.
  • A single-column Boolean batch never gets an optimized predicate (coalesce.rs), so single_boolean only measures the lazy index iterator. Batches with more than one column get precomputed Indices, which none of these numbers cover.

The fused loop would look roughly like this, plus the trailing partial word:

for (i, m) in filter_words.enumerate() {
    if m == 0 {
        continue;
    }
    let k = m.count_ones() as usize;
    values.append_word(compress(value_words.chunk(i), m), k);
    if let Some(validity) = &validity_words {
        nulls.append_word(compress(validity.chunk(i), m), k);
    }
}

This needs no intermediate array or copy, and it scans the filter once for values and validity together. Its cost is per filter word, with no branch on the values. For precomputed Indices at or below len / 64, gathering one index at a time would stay, which is the cutoff filter_bits already uses. That cutoff follows from the word size (fewer than one kept bit per word), not from a benchmark. At 0.001 with independent bits, almost every non-empty word holds one selected row, so I'd expect this to tie the per-bit path there rather than beat it.

BooleanBufferBuilder::append_word exists, and the Parquet reader already builds validity bitmaps with compress followed by append_word (definition_levels.rs). NullBufferBuilder has no equivalent. An append_word there that calls append_n_non_nulls while every bit is valid would keep its lazy allocation. The primitive sparse path filters nulls the same way, filter_nulls followed by append_buffer, so the validity half could be a shared helper for both.

Would you be open to trying this in place of the per-bit path? If the prototype holds up on both x86_64 and aarch64, NullBufferBuilder::append_word could go in a separate PR first. A benchmark PR with runs of selected rows and a multi-column Boolean case would show whether it holds beyond these inputs.

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (4c23338) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.61     33.5±0.47ms        ? ?/sec    1.00     20.8±0.05ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.41      3.0±0.03ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.08    538.3±3.03µs        ? ?/sec    1.00    498.3±1.93µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.09    113.4±0.27µs        ? ?/sec    1.00    104.3±0.15µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.15     46.7±0.33ms        ? ?/sec    1.00     21.7±0.11ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.37      4.6±0.02ms        ? ?/sec    1.00      3.3±0.02ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    938.9±2.83µs        ? ?/sec    1.00    885.6±1.45µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.04    203.5±0.56µs        ? ?/sec    1.00    196.2±0.27µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.23     19.5±0.07ms        ? ?/sec    1.00     15.8±0.06ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.17      2.6±0.01ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.03    879.3±1.30µs        ? ?/sec    1.00    855.2±5.33µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.00      2.3±0.00ms        ? ?/sec    1.07      2.4±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.25     28.3±0.11ms        ? ?/sec    1.00     22.7±0.08ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.15      4.1±0.01ms        ? ?/sec    1.00      3.5±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.03   1733.9±3.92µs        ? ?/sec    1.00   1691.1±8.44µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.00      3.0±0.01ms        ? ?/sec    1.05      3.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.28     13.5±0.08ms        ? ?/sec    1.00     10.5±0.10ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.26   1551.9±8.40µs        ? ?/sec    1.00   1234.2±5.16µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.11    356.0±0.75µs        ? ?/sec    1.00    320.1±0.75µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.05    241.7±0.26µs        ? ?/sec    1.00    230.1±0.21µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.20     20.1±0.09ms        ? ?/sec    1.00     16.8±0.07ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.19      2.5±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.08    619.3±0.81µs        ? ?/sec    1.00    573.4±1.73µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.04    434.4±0.33µs        ? ?/sec    1.00    419.2±0.26µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-2fege4dq-b5d3eead-zpss

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

uname:

Linux bench-c6325112762-3736-zz2q9 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 20.7 MiB
Avg memory 13.6 MiB
CPU user 262.8s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 265.1s
Peak memory 20.5 MiB
Avg memory 13.6 MiB
CPU user 258.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (4c23338) to 01a9917 (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.60     33.4±0.50ms        ? ?/sec    1.00     20.8±0.05ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.41      3.0±0.02ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.09    542.1±2.37µs        ? ?/sec    1.00    497.2±1.34µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.09    113.6±0.26µs        ? ?/sec    1.00    104.6±0.28µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        2.14     46.7±0.13ms        ? ?/sec    1.00     21.8±0.13ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.36      4.5±0.01ms        ? ?/sec    1.00      3.3±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.06    939.2±1.47µs        ? ?/sec    1.00    887.8±2.83µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.04    203.8±0.57µs        ? ?/sec    1.00    196.4±0.31µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.22     19.4±0.07ms        ? ?/sec    1.00     15.9±0.10ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.18      2.6±0.00ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.01    884.2±2.02µs        ? ?/sec    1.00    873.7±6.05µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.00      2.3±0.00ms        ? ?/sec    1.06      2.4±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.22     28.0±0.08ms        ? ?/sec    1.00     22.9±0.15ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.14      4.1±0.01ms        ? ?/sec    1.00      3.6±0.02ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.02   1739.0±5.27µs        ? ?/sec    1.00   1707.1±8.38µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.00      3.0±0.01ms        ? ?/sec    1.06      3.2±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.30     13.6±0.08ms        ? ?/sec    1.00     10.5±0.09ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.23   1547.0±4.21µs        ? ?/sec    1.00   1262.8±8.39µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.11    357.8±0.99µs        ? ?/sec    1.00    321.1±0.64µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.05    241.7±0.33µs        ? ?/sec    1.00    230.2±0.20µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.21     20.3±0.11ms        ? ?/sec    1.00     16.8±0.09ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.18      2.5±0.01ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.09    622.0±1.15µs        ? ?/sec    1.00    571.4±1.37µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.04    434.5±1.00µs        ? ?/sec    1.00    419.8±0.32µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-1jz5nqdi-de95f2a3-wthn

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

uname:

Linux bench-c6325140593-3737-sc69p 6.12.94+ #1 SMP Fri Aug 21 08:00:16 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 24.9 MiB
Avg memory 13.7 MiB
CPU user 263.7s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 265.1s
Peak memory 15.8 MiB
Avg memory 13.6 MiB
CPU user 260.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

@mbutrovich That makes sense, though it seems like a larger departure from the current approach. What do you think about dropping the additional thresholds from the latest commit and merging the simpler version first? We could then add the new NullBufferBuilder method in a follow-up before exploring the word-at-a-time optimization.

@mbutrovich

Copy link
Copy Markdown
Contributor

What do you think about dropping the additional thresholds from the latest commit and merging the simpler version first? We could then add the new NullBufferBuilder method in a follow-up before exploring the word-at-a-time optimization.

I don't think we need to rush this and would rather get the design right. I'm also not sure the per-bit path is the simpler version, with one cutoff or two. Each cutoff is tuned to the benchmark inputs I listed above, and dropping the second one brings back the 0.005 regression from my runs. I'd rather not merge a cutoff that the next PR removes.

If you'd like to land something first, what about the version with no cutoff at all, where copy_rows_by_filter_from always calls filter.filter()? That's the "kernel" column in my table, and it beat main in nine of ten cases. As I read it, the gain comes from skipping the concat in GenericInProgressArray::finish. The fused loop would then replace only that one call, so nothing merged along the way gets deleted. The order would be this PR, then NullBufferBuilder::append_word, then the fused loop. What do you think?

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

The order would be this PR, then NullBufferBuilder::append_word, then the fused loop. What do you think?
yea makes sense to me

Always use the existing filter kernel and append its output into the Boolean builders. This keeps the final concat avoidance without benchmark-specific sparse cutoffs.
@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (b4ddd37) to df4dc3e (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@Rich-T-kid

Copy link
Copy Markdown
Contributor Author

run benchmark coalesce_kernels
env:
BENCH_FILTER: "single_boolean"

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark starting (GKE) | trigger

Target: coalesce_kernels

Sharding factor: 1 (1 workers).

Comparing rich-T-kid/coalescer-boolean-take (b4ddd37) to df4dc3e (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1

Results will be posted when all workers finish.


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (b4ddd37) to df4dc3e (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.53     33.5±0.57ms        ? ?/sec    1.00     21.9±0.12ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.38      3.0±0.04ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.07    539.4±2.96µs        ? ?/sec    1.00    505.6±2.26µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.08    113.0±0.36µs        ? ?/sec    1.00    104.7±0.46µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        1.43     46.6±0.35ms        ? ?/sec    1.00     32.7±0.48ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.30      4.6±0.03ms        ? ?/sec    1.00      3.5±0.02ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.05    938.4±2.27µs        ? ?/sec    1.00    890.1±1.54µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.05    202.9±0.30µs        ? ?/sec    1.00    192.9±0.27µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.24     19.3±0.08ms        ? ?/sec    1.00     15.6±0.08ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.19      2.6±0.00ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.03    879.4±3.32µs        ? ?/sec    1.00    851.6±1.87µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.06      2.4±0.00ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.23     28.0±0.10ms        ? ?/sec    1.00     22.7±0.13ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.16      4.1±0.01ms        ? ?/sec    1.00      3.6±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.03   1739.8±6.57µs        ? ?/sec    1.00   1689.3±5.60µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.06      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.27     15.2±0.11ms        ? ?/sec    1.00     12.0±0.21ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.22  1709.9±12.82µs        ? ?/sec    1.00  1396.8±25.54µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.12    394.8±1.03µs        ? ?/sec    1.00    352.4±2.14µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.05    258.5±0.18µs        ? ?/sec    1.00    247.2±0.27µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.20     21.8±0.14ms        ? ?/sec    1.00     18.2±0.22ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.18      2.7±0.01ms        ? ?/sec    1.00      2.3±0.02ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    661.6±1.26µs        ? ?/sec    1.00    619.6±1.43µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.03    461.8±0.42µs        ? ?/sec    1.00    449.6±0.28µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-164vnrqr-001ae743-l956

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

uname:

Linux bench-c6370779259-3798-79nw8 6.12.105+ #1 SMP Sat Sep  5 07:54:11 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 25.0 MiB
Avg memory 13.9 MiB
CPU user 265.8s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 260.1s
Peak memory 26.0 MiB
Avg memory 13.7 MiB
CPU user 257.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Target: coalesce_kernels

Comparing rich-T-kid/coalescer-boolean-take (b4ddd37) to df4dc3e (merge-base) diff

Run configuration
run benchmark coalesce_kernels
env:
  BENCH_FILTER: single_boolean
shards: 1
Details
group                                                               base                                   changed
-----                                                               ----                                   -------
filter: single_boolean, 8192, nulls: 0, selectivity: 0.001          1.50     33.4±0.34ms        ? ?/sec    1.00     22.3±0.41ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.01           1.35      3.0±0.02ms        ? ?/sec    1.00      2.2±0.03ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.1            1.06    538.0±1.89µs        ? ?/sec    1.00    506.9±2.35µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0, selectivity: 0.8            1.08    113.3±0.24µs        ? ?/sec    1.00    104.9±0.34µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.001        1.41     46.5±0.18ms        ? ?/sec    1.00     33.0±0.38ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.01         1.28      4.5±0.02ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.1          1.05    943.0±2.69µs        ? ?/sec    1.00    897.7±3.11µs        ? ?/sec
filter: single_boolean, 8192, nulls: 0.1, selectivity: 0.8          1.05    203.4±1.31µs        ? ?/sec    1.00    194.3±0.31µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.001      1.23     19.2±0.07ms        ? ?/sec    1.00     15.7±0.09ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.01       1.19      2.6±0.00ms        ? ?/sec    1.00      2.2±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.1        1.03    877.1±4.04µs        ? ?/sec    1.00    850.1±1.35µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0, selectivity: 0.8        1.08      2.5±0.00ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.001    1.23     27.9±0.09ms        ? ?/sec    1.00     22.8±0.15ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.01     1.16      4.1±0.01ms        ? ?/sec    1.00      3.5±0.01ms        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.1      1.03   1740.4±4.80µs        ? ?/sec    1.00   1693.5±3.62µs        ? ?/sec
interleave: single_boolean, 8192, nulls: 0.1, selectivity: 0.8      1.05      3.2±0.01ms        ? ?/sec    1.00      3.0±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.001            1.27     15.0±0.08ms        ? ?/sec    1.00     11.8±0.12ms        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.01             1.22   1706.4±4.01µs        ? ?/sec    1.00  1404.3±18.63µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.1              1.10    388.8±1.01µs        ? ?/sec    1.00    352.5±1.79µs        ? ?/sec
take: single_boolean, 8192, nulls: 0, selectivity: 0.8              1.04    256.4±0.16µs        ? ?/sec    1.00    247.7±0.27µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.001          1.19     21.6±0.11ms        ? ?/sec    1.00     18.1±0.10ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.01           1.18      2.7±0.01ms        ? ?/sec    1.00      2.3±0.01ms        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.1            1.07    659.5±1.11µs        ? ?/sec    1.00    619.1±2.41µs        ? ?/sec
take: single_boolean, 8192, nulls: 0.1, selectivity: 0.8            1.02    460.7±0.36µs        ? ?/sec    1.00    450.8±0.38µs        ? ?/sec

Per-runner information
coalesce_kernels — shard 1/1

Node: gk3-benchmark-cluster-nap-1poo5pys-97e0df26-vphg

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

uname:

Linux bench-c6370780904-3799-pf9rr 6.12.105+ #1 SMP Sat Sep  5 07:54:11 UTC 2026 aarch64 GNU/Linux

BENCH_COMMAND:

cargo bench --features=arrow,async,test_common,experimental,object_store --bench coalesce_kernels
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
Resource Usage

base (merge-base)

Metric Value
Wall time 270.1s
Peak memory 16.6 MiB
Avg memory 13.7 MiB
CPU user 265.7s
CPU sys 0.3s
Peak spill 0 B

branch

Metric Value
Wall time 265.1s
Peak memory 15.4 MiB
Avg memory 13.7 MiB
CPU user 262.0s
CPU sys 0.3s
Peak spill 0 B

File an issue against this benchmark runner

@Rich-T-kid

Rich-T-kid commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

nice, results look good. Created #11867 as a follow up. results also look good there

sdf-jkl pushed a commit to sdf-jkl/arrow-rs that referenced this pull request Oct 23, 2026
## Why
Exercise the sparse filter path around its 1/128 selectivity cutoff.
This follows up on
apache#11732 (comment).

## What changed
Added 0.005 selectivity to the coalesce filter benchmark matrix.

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

Thanks @Rich-T-kid for taking the simpler route. Happy to review the followup PRs!

wleeaf pushed a commit to wleeaf/arrow-rs that referenced this pull request Oct 24, 2026
# Which issue does this PR close?

N/A. Follow-up to apache#11732.

# Rationale for this change

Callers with packed validity bits currently need to append them one bit
at a time or first build a `NullBuffer`.

# What changes are included in this PR?

This adds `NullBufferBuilder::append_word`, matching
`BooleanBufferBuilder::append_word` while preserving lazy allocation for
all-valid words. It also adds focused unit tests and benchmarks for
different validity patterns.

# Are these changes tested?

The tests cover full and partial all-valid words without
materialization, plus a mixed partial word at an unaligned offset and an
all-valid append after materialization. The benchmark covers all-valid,
very sparse, sparse, densely packed, and alternating validity words.

# Are there any significant user-facing changes?

Adds `NullBufferBuilder::append_word`.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrow-kernels Crates that transform arrow data (e.g. compute, cast) performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Specialize BatchCoalescer for BooleanArray

3 participants