Skip to content

Fold aggregates with masked and lane-parallel kernels - #10947

Open
robert3005 wants to merge 7 commits into
developfrom
rk/fold-masked
Open

robert3005 wants to merge 7 commits into
developfrom
rk/fold-masked

Conversation

@robert3005

@robert3005 robert3005 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Most primitive aggregates ran one element at a time: with nulls they walked runs of valid values, and float sums, float min/max and 64-bit sums didn't vectorize because the compiler can't reorder their folds. This PR adds fold_masked, fold_lanes and fold_lanes_masked to vortex-compute, which read null lanes as an identity and fold into per-lane accumulators, and uses them in min/max, sum and NaN count. Decimals stored in at most 64 bits are summed with the same vectorized i64 sums. Each reduction is now branch-free, vectorizes on every target and costs the same at any validity density: float sums are 4.6×–8.8× faster (up to 30× with scattered nulls), float max 2.4×–8.8×, 64-bit sums 1.8×–3.4×, and i32 min/max with scattered nulls goes from ~45 µs to ~8–9 µs. Validity::and of two bool validities, such as a nullable array masked by another, now ANDs their bits word by word up front instead of building a lazy conjunction that every reader evaluated again; masking a nullable column and counting its nulls goes from 1.62 µs to 1.36 µs.

@codspeed

codspeed Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 8 benchmarks

3 warnings

⚠️ Walltime results may be unreliable

Some benchmarks used the Walltime instrument outside CodSpeed Macro Runners, which can make the results inconsistent.

Learn more about Macro Runners

See affected benchmarks

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

⚡ 35 improved benchmarks
❌ 8 regressed benchmarks
✅ 2263 untouched benchmarks
🆕 61 new benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ CPU Simulation filter_powerlaw_by_random[10000] 142.2 ns 247.5 ns -42.55%
❌ CPU Simulation sum[msp_i64_p18_canonical] 129 µs 217.9 µs -40.8%
❌ CPU Simulation sum[msp_i64_p38] 143.2 µs 232.4 µs -38.37%
❌ CPU Simulation min_max_decimal_i256[ScatteredNulls] 672.5 µs 1,001.7 µs -32.86%
❌ CPU Simulation missing_stats[16] 66.8 µs 85 µs -21.45%
❌ CPU Simulation compare_bool_nullable 48.1 µs 55.2 µs -12.86%
❌ CPU Simulation take_map[(0.005, 0.5)] 87.5 µs 98 µs -10.75%
❌ CPU Simulation take_map[(0.005, 1.0)] 147 µs 163.6 µs -10.15%
⚡ CPU Simulation sum_i32_nulls_scattered 690.4 µs 99.4 µs ×6.9
⚡ CPU Simulation sum_v2_i32_nulls_scattered 733 µs 124.8 µs ×5.9
⚡ CPU Simulation max_i32_nulls_scattered 766.6 µs 138.7 µs ×5.5
⚡ CPU Simulation integer_stats_all_nullable 2,432.7 µs 517.6 µs ×4.7
⚡ CPU Simulation cast_i32_to_u32[8192] 389.2 µs 122.5 µs ×3.2
⚡ CPU Simulation integer_stats_nullable 1,789.6 µs 563.9 µs ×3.2
⚡ CPU Simulation min_max[msp_i32_p18_nullable] 226.3 µs 115.3 µs +96.36%
⚡ CPU Simulation sum[msp_i32_p18_nullable] 156.5 µs 87.5 µs +79%
⚡ CPU Simulation max_f64 313.6 µs 189.5 µs +65.48%
⚡ Walltime threshold_neon[64] 4.4 µs 2.7 µs +64.15%
⚡ Walltime filter_neon[64] 2.7 µs 1.8 µs +51.02%
⚡ CPU Simulation sum_f64 204.8 µs 135.7 µs +50.92%
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing rk/fold-masked (1df80b0) with develop (d4d9234)

Open in CodSpeed

@robert3005 robert3005 changed the title Fold nullable integer min, max and sum with a masked lane kernel Fold nullable min, max, sum and NaN counts with a masked lane kernel Oct 28, 2026
claude and others added 3 commits October 28, 2026 21:52
With nulls present, the primitive min/max and sum kernels walked the runs of
valid values one at a time, so a nullable column with short runs, such as one
with half its rows null, reduced thousands of one- or two-element slices.

Add a masked reduction lane kernel, IndexedFoldExt::fold_masked, which folds
every lane into an accumulator and reads null lanes as an identity of the
fold. Lanes are selected against constant bits of each 32-lane half of the
validity word, which needs no per-lane variable shift and so vectorizes on
baseline x86-64, and halves with no valid lane are skipped.

Integer min/max read null lanes as a valid value, and integer sums narrower
than 64 bits read them as zero, so both cost the same at any validity
density. 64-bit integer sums keep their per-element overflow check, and
floats keep their in-order runs.

Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1HnweRGxeDWgQwXXM6f5s
Apply fold_masked to the other aggregate kernels that walked runs of valid
values or zipped values with validity bits:

- Float min/max fold total-order keys, integers that order exactly as
  total_cmp does, so the reduction is plain integer min/max and its result is
  bit-for-bit that of the previous total_cmp reduction, all-valid or not.
- Decimal min/max read null lanes as a valid value, like integers.
- Float NaN counts read null lanes as zero, which is not NaN.
- Float sums read null lanes as zero, adding the values in the same order,
  which leaves the result unchanged.

Decimal sums and the grouped sums keep their paths: decimal sums are bound by
their checked adds, and grouped sums over short groups pay more to set up the
fold per group than the fold saves.

Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1HnweRGxeDWgQwXXM6f5s
Float sums, float min/max and 64-bit integer sums did not vectorize: the
compiler cannot reorder float adds, float compares or checked adds, so each
ran one element at a time, and with nulls each run of valid values ran
separately.

Add IndexedFoldExt::fold_lanes and fold_lanes_masked. They fold lane i into
accumulator i % LANES and merge the accumulators at the end, so one row of
lanes is one vector step for any fold. The masked form tests each lane
against a constant bit of the validity word, with no branch. An opaque
barrier before each row stops the vectorizers from packing one lane of
several rows with strided loads.

Use the folds in the aggregates:

- Float sums use lane folds. NaN skipping runs a second pass only when
  the first sum is NaN.
- Float min/max use float compares, one fold per extremum. A cold pass
  settles a valid NaN and the sign of a zero extremum.
- 64-bit sums add with wrapping and OR together a bound on each value's
  magnitude. Values past the bound get an exact 128-bit sum, so a sum
  overflows only if its exact total does not fit.
- Narrower integer sums use 16 lanes, except signed values on x86-64
  without SSE4.1, which has no vector sign extension.

On Graviton4, Sapphire Rapids, Zen 4 and Apple M4 the float sums are
4.6x to 8.8x faster, and up to 30x with scattered nulls. Float max is
2.4x to 8.8x faster, and 64-bit sums are 1.8x to 3.4x faster.

Signed-off-by: Robert Kruszewski <github@robertk.io>
Claude-Session: https://claude.ai/code/session_018SWbEqgj32dnKrPu3naMzN
@robert3005 robert3005 added the changelog/performance A performance improvement label Oct 29, 2026
Format the changed crates with the pinned nightly. Let clippy accept
v - v in the float min/max kernel, because it finds NaN and infinite
values. Run integer_stats_all_nullable on 16K values instead of 64K.

Signed-off-by: Robert Kruszewski <github@robertk.io>
@robert3005 robert3005 changed the title Fold nullable min, max, sum and NaN counts with a masked lane kernel Fold aggregates with masked and lane-parallel kernels Oct 29, 2026
Decimal values stored in i8 to i64 use the i64 sum kernels, with and
without nulls. Wider values, or an i64 sum that overflows, use the
checked loop in the result type.

Signed-off-by: Robert Kruszewski <github@robertk.io>
@robert3005 robert3005 added the action/bench-compress Run only the compression benchmark on this PR label Oct 29, 2026
@github-actions github-actions Bot removed the action/bench-compress Run only the compression benchmark on this PR label Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Polar Signals Profiling Results

Latest Run

Status Commit Job Attempt Link
🟢 Done d5045ac compress-bench 1 Explore Profiling Data

Powered by Polar Signals Cloud

@github-actions

Copy link
Copy Markdown
Contributor

Benchmarks: Compression 📖

Commits: PR d5045ac3 vs base 40e0b1cc


vortex / vortex-file-compressed / ns (0.995x ➖, 0↑ 0↓)
name ns (PR / base / %diff)
compress time/Arade 488795523 / 492530910 / -0.8%
compress time/Bimbo 1928516941 / 1954568631 / -1.3%
compress time/CMSprovider 959515235 / 961331124 / -0.2%
compress time/Euro2016 164775085 / 167977422 / -1.9%
compress time/Food 223606496 / 227964617 / -1.9%
compress time/HashTags 370302133 / 376970640 / -1.8%
compress time/TPC-H l_comment canonical 382698480 / 391281085 / -2.2%
compress time/TPC-H l_comment chunked 384680690 / 393816980 / -2.3%
compress time/taxi 183250282 / 185029246 / -1.0%
compress time/wide table cols=100 chunks=1 rows=1000 4262734 / 4176641 / +2.1%
compress time/wide table cols=100 chunks=50 rows=1000 4420081 / 4135705 / +6.9%
compress time/wide table cols=1000 chunks=1 rows=1000 40941320 / 40163291 / +1.9%
compress time/wide table cols=1000 chunks=50 rows=1000 40810485 / 40794368 / +0.0%
compress time/wide table cols=10000 chunks=1 rows=1000 466433397 / 466886607 / -0.1%
compress time/wide table cols=10000 chunks=50 rows=1000 458541243 / 464750865 / -1.3%
decompress time/Arade 13659114 / 13726469 / -0.5%
decompress time/Bimbo 64274680 / 64231770 / +0.1%
decompress time/CMSprovider 37912951 / 38119239 / -0.5%
decompress time/Euro2016 12720125 / 12746267 / -0.2%
decompress time/Food 3739892 / 3748109 / -0.2%
decompress time/HashTags 36608072 / 36354226 / +0.7%
decompress time/TPC-H l_comment canonical 14516989 / 14432583 / +0.6%
decompress time/TPC-H l_comment chunked 14397352 / 14423081 / -0.2%
decompress time/taxi 9530390 / 9715845 / -1.9%
decompress time/wide table cols=100 chunks=1 rows=1000 1392769 / 1403719 / -0.8%
decompress time/wide table cols=100 chunks=50 rows=1000 1369726 / 1397289 / -2.0%
decompress time/wide table cols=1000 chunks=1 rows=1000 12809918 / 14099798 / -9.1%
decompress time/wide table cols=1000 chunks=50 rows=1000 14191489 / 14084238 / +0.8%
decompress time/wide table cols=10000 chunks=1 rows=1000 139722906 / 137600705 / +1.5%
decompress time/wide table cols=10000 chunks=50 rows=1000 140958915 / 139796010 / +0.8%
vortex / vortex-file-compressed / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
vortex-file-compressed size/Arade 142214220 / 142214220 / +0.0%
vortex-file-compressed size/Bimbo 458581412 / 458581412 / +0.0%
vortex-file-compressed size/CMSprovider 420808940 / 420808940 / +0.0%
vortex-file-compressed size/Euro2016 164571836 / 164571836 / +0.0%
vortex-file-compressed size/Food 38951432 / 38951432 / +0.0%
vortex-file-compressed size/HashTags 195467452 / 195467460 / -0.0%
vortex-file-compressed size/TPC-H l_comment canonical 178709224 / 178709224 / +0.0%
vortex-file-compressed size/TPC-H l_comment chunked 178709224 / 178709224 / +0.0%
vortex-file-compressed size/taxi 49998508 / 49998508 / +0.0%
vortex-file-compressed size/wide table cols=100 chunks=1 rows=1000 935376 / 935376 / +0.0%
vortex-file-compressed size/wide table cols=100 chunks=50 rows=1000 935376 / 935376 / +0.0%
vortex-file-compressed size/wide table cols=1000 chunks=1 rows=1000 9336872 / 9336872 / +0.0%
vortex-file-compressed size/wide table cols=1000 chunks=50 rows=1000 9336872 / 9336872 / +0.0%
vortex-file-compressed size/wide table cols=10000 chunks=1 rows=1000 93387872 / 93387872 / +0.0%
vortex-file-compressed size/wide table cols=10000 chunks=50 rows=1000 93387872 / 93387872 / +0.0%
vortex / vortex-file-compressed / ratio (0.998x ➖, 1↑ 1↓)
name ratio (PR / base / %diff)
vortex:parquet-zstd ratio compress time/Arade 0.668215752 / 0.674416151 / -0.9%
vortex:parquet-zstd ratio compress time/Bimbo 0.971794385 / 0.991454415 / -2.0%
vortex:parquet-zstd ratio compress time/CMSprovider 0.902649588 / 0.910039289 / -0.8%
vortex:parquet-zstd ratio compress time/Euro2016 0.255616642 / 0.26045121 / -1.9%
vortex:parquet-zstd ratio compress time/Food 0.701055761 / 0.716926121 / -2.2%
vortex:parquet-zstd ratio compress time/HashTags 1.0868072 / 1.10506169 / -1.7%
vortex:parquet-zstd ratio compress time/TPC-H l_comment canonical 0.362268289 / 0.372343028 / -2.7%
vortex:parquet-zstd ratio compress time/TPC-H l_comment chunked 0.364347634 / 0.374290121 / -2.7%
vortex:parquet-zstd ratio compress time/taxi 0.949659732 / 0.961439039 / -1.2%
vortex:parquet-zstd ratio compress time/wide table cols=100 chunks=1 rows=1000 1.22016492 / 1.18209341 / +3.2%
vortex:parquet-zstd ratio compress time/wide table cols=100 chunks=50 rows=1000 1.33241925 / 1.14380059 / +16.5% 🔴
vortex:parquet-zstd ratio compress time/wide table cols=1000 chunks=1 rows=1000 1.14656694 / 1.14243725 / +0.4%
vortex:parquet-zstd ratio compress time/wide table cols=1000 chunks=50 rows=1000 1.15266279 / 1.14239702 / +0.9%
vortex:parquet-zstd ratio compress time/wide table cols=10000 chunks=1 rows=1000 1.26514536 / 1.24644643 / +1.5%
vortex:parquet-zstd ratio compress time/wide table cols=10000 chunks=50 rows=1000 1.24696051 / 1.23814274 / +0.7%
vortex:parquet-zstd ratio decompress time/Arade 0.278819992 / 0.280282418 / -0.5%
vortex:parquet-zstd ratio decompress time/Bimbo 0.724562377 / 0.718482877 / +0.8%
vortex:parquet-zstd ratio decompress time/CMSprovider 0.370270181 / 0.370739515 / -0.1%
vortex:parquet-zstd ratio decompress time/Euro2016 0.0848958692 / 0.0849478066 / -0.1%
vortex:parquet-zstd ratio decompress time/Food 0.149514123 / 0.148953381 / +0.4%
vortex:parquet-zstd ratio decompress time/HashTags 0.0877310223 / 0.0868703107 / +1.0%
vortex:parquet-zstd ratio decompress time/TPC-H l_comment canonical 0.176908846 / 0.175098961 / +1.0%
vortex:parquet-zstd ratio decompress time/TPC-H l_comment chunked 0.175244234 / 0.175266818 / -0.0%
vortex:parquet-zstd ratio decompress time/taxi 0.163164749 / 0.165527159 / -1.4%
vortex:parquet-zstd ratio decompress time/wide table cols=100 chunks=1 rows=1000 0.683549156 / 0.680850166 / +0.4%
vortex:parquet-zstd ratio decompress time/wide table cols=100 chunks=50 rows=1000 0.665374513 / 0.685370585 / -2.9%
vortex:parquet-zstd ratio decompress time/wide table cols=1000 chunks=1 rows=1000 0.538610506 / 0.60171528 / -10.5% 🟢
vortex:parquet-zstd ratio decompress time/wide table cols=1000 chunks=50 rows=1000 0.604027114 / 0.604102328 / -0.0%
vortex:parquet-zstd ratio decompress time/wide table cols=10000 chunks=1 rows=1000 0.541429609 / 0.542571931 / -0.2%
vortex:parquet-zstd ratio decompress time/wide table cols=10000 chunks=50 rows=1000 0.55379755 / 0.556903502 / -0.6%
vortex:parquet-zstd size/Arade 0.551187395 / 0.551187395 / -0.0%
vortex:parquet-zstd size/Bimbo 1.19261584 / 1.19261584 / +0.0%
vortex:parquet-zstd size/CMSprovider 1.11653605 / 1.11653605 / +0.0%
vortex:parquet-zstd size/Euro2016 1.33821035 / 1.33821035 / -0.0%
vortex:parquet-zstd size/Food 1.09109181 / 1.09109181 / -0.0%
vortex:parquet-zstd size/HashTags 1.4642021 / 1.46420216 / -0.0%
vortex:parquet-zstd size/TPC-H l_comment canonical 1.12851233 / 1.12851233 / -0.0%
vortex:parquet-zstd size/TPC-H l_comment chunked 1.12851233 / 1.12851233 / -0.0%
vortex:parquet-zstd size/taxi 0.904399792 / 0.904399792 / -0.0%
vortex:parquet-zstd size/wide table cols=100 chunks=1 rows=1000 1.00318746 / 1.00318746 / -0.0%
vortex:parquet-zstd size/wide table cols=100 chunks=50 rows=1000 1.00318746 / 1.00318746 / -0.0%
vortex:parquet-zstd size/wide table cols=1000 chunks=1 rows=1000 1.00138009 / 1.00138009 / -0.0%
vortex:parquet-zstd size/wide table cols=1000 chunks=50 rows=1000 1.00138009 / 1.00138009 / -0.0%
vortex:parquet-zstd size/wide table cols=10000 chunks=1 rows=1000 1.00158589 / 1.00158589 / -0.0%
vortex:parquet-zstd size/wide table cols=10000 chunks=50 rows=1000 1.00158589 / 1.00158589 / -0.0%
vortex / parquet / ns (0.997x ➖, 0↑ 0↓)
name ns (PR / base / %diff)
parquet_rs-zstd compress time/Arade 731493566 / 730307110 / +0.2%
parquet_rs-zstd compress time/Bimbo 1984490723 / 1971415529 / +0.7%
parquet_rs-zstd compress time/CMSprovider 1062998585 / 1056362220 / +0.6%
parquet_rs-zstd compress time/Euro2016 644617985 / 644947750 / -0.1%
parquet_rs-zstd compress time/Food 318956791 / 317975047 / +0.3%
parquet_rs-zstd compress time/HashTags 340724769 / 341130855 / -0.1%
parquet_rs-zstd compress time/TPC-H l_comment canonical 1056395197 / 1050861854 / +0.5%
parquet_rs-zstd compress time/TPC-H l_comment chunked 1055806746 / 1052170384 / +0.3%
parquet_rs-zstd compress time/taxi 192964149 / 192450315 / +0.3%
parquet_rs-zstd compress time/wide table cols=100 chunks=1 rows=1000 3493572 / 3533258 / -1.1%
parquet_rs-zstd compress time/wide table cols=100 chunks=50 rows=1000 3317335 / 3615757 / -8.3%
parquet_rs-zstd compress time/wide table cols=1000 chunks=1 rows=1000 35707745 / 35155796 / +1.6%
parquet_rs-zstd compress time/wide table cols=1000 chunks=50 rows=1000 35405398 / 35709449 / -0.9%
parquet_rs-zstd compress time/wide table cols=10000 chunks=1 rows=1000 368679689 / 374574145 / -1.6%
parquet_rs-zstd compress time/wide table cols=10000 chunks=50 rows=1000 367727157 / 375361297 / -2.0%
parquet_rs-zstd decompress time/Arade 48989005 / 48973707 / +0.0%
parquet_rs-zstd decompress time/Bimbo 88708277 / 89399166 / -0.8%
parquet_rs-zstd decompress time/CMSprovider 102392666 / 102819466 / -0.4%
parquet_rs-zstd decompress time/Euro2016 149832084 / 150048218 / -0.1%
parquet_rs-zstd decompress time/Food 25013637 / 25162967 / -0.6%
parquet_rs-zstd decompress time/HashTags 417276250 / 418488500 / -0.3%
parquet_rs-zstd decompress time/TPC-H l_comment canonical 82059147 / 82425292 / -0.4%
parquet_rs-zstd decompress time/TPC-H l_comment chunked 82155924 / 82292137 / -0.2%
parquet_rs-zstd decompress time/taxi 58409614 / 58696380 / -0.5%
parquet_rs-zstd decompress time/wide table cols=100 chunks=1 rows=1000 2037555 / 2061715 / -1.2%
parquet_rs-zstd decompress time/wide table cols=100 chunks=50 rows=1000 2058579 / 2038735 / +1.0%
parquet_rs-zstd decompress time/wide table cols=1000 chunks=1 rows=1000 23783268 / 23432674 / +1.5%
parquet_rs-zstd decompress time/wide table cols=1000 chunks=50 rows=1000 23494788 / 23314325 / +0.8%
parquet_rs-zstd decompress time/wide table cols=10000 chunks=1 rows=1000 258062920 / 253608226 / +1.8%
parquet_rs-zstd decompress time/wide table cols=10000 chunks=50 rows=1000 254531489 / 251023758 / +1.4%
vortex / parquet / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
parquet size/Arade 258014282 / 258014282 / +0.0%
parquet size/Bimbo 384517292 / 384517292 / +0.0%
parquet size/CMSprovider 376887911 / 376887911 / +0.0%
parquet size/Euro2016 122979049 / 122979049 / +0.0%
parquet size/Food 35699500 / 35699500 / +0.0%
parquet size/HashTags 133497590 / 133497590 / +0.0%
parquet size/TPC-H l_comment canonical 158358238 / 158358238 / +0.0%
parquet size/TPC-H l_comment chunked 158358238 / 158358238 / +0.0%
parquet size/taxi 55283635 / 55283635 / +0.0%
parquet size/wide table cols=100 chunks=1 rows=1000 932404 / 932404 / +0.0%
parquet size/wide table cols=100 chunks=50 rows=1000 932404 / 932404 / +0.0%
parquet size/wide table cols=1000 chunks=1 rows=1000 9324004 / 9324004 / +0.0%
parquet size/wide table cols=1000 chunks=50 rows=1000 9324004 / 9324004 / +0.0%
parquet size/wide table cols=10000 chunks=1 rows=1000 93240004 / 93240004 / +0.0%
parquet size/wide table cols=10000 chunks=50 rows=1000 93240004 / 93240004 / +0.0%
vortex / arrow-ipc / ns (0.997x ➖, 0↑ 0↓)
name ns (PR / base / %diff)
arrow-ipc compress time/Arade 96434238 / 97040324 / -0.6%
arrow-ipc compress time/Bimbo 603615376 / 618371884 / -2.4%
arrow-ipc compress time/CMSprovider 377817003 / 381148731 / -0.9%
arrow-ipc compress time/Euro2016 38165599 / 38469411 / -0.8%
arrow-ipc compress time/Food 40090916 / 40359901 / -0.7%
arrow-ipc compress time/HashTags 77717721 / 78262364 / -0.7%
arrow-ipc compress time/TPC-H l_comment canonical 129758597 / 128890113 / +0.7%
arrow-ipc compress time/TPC-H l_comment chunked 128173383 / 129573005 / -1.1%
arrow-ipc compress time/taxi 59483527 / 59796608 / -0.5%
arrow-ipc compress time/wide table cols=100 chunks=1 rows=1000 193669 / 195193 / -0.8%
arrow-ipc compress time/wide table cols=100 chunks=50 rows=1000 195899 / 191935 / +2.1%
arrow-ipc compress time/wide table cols=1000 chunks=1 rows=1000 2206921 / 2205101 / +0.1%
arrow-ipc compress time/wide table cols=1000 chunks=50 rows=1000 2179947 / 2167292 / +0.6%
arrow-ipc compress time/wide table cols=10000 chunks=1 rows=1000 24878419 / 24791492 / +0.4%
arrow-ipc compress time/wide table cols=10000 chunks=50 rows=1000 24875192 / 24727337 / +0.6%
arrow-ipc decompress time/Arade 218488978 / 218171470 / +0.1%
arrow-ipc decompress time/Bimbo 417417996 / 415345462 / +0.5%
arrow-ipc decompress time/CMSprovider 673945262 / 697000842 / -3.3%
arrow-ipc decompress time/Euro2016 85819958 / 85617110 / +0.2%
arrow-ipc decompress time/Food 67403557 / 67549994 / -0.2%
arrow-ipc decompress time/HashTags 165387926 / 165753891 / -0.2%
arrow-ipc decompress time/TPC-H l_comment canonical 191670851 / 190337079 / +0.7%
arrow-ipc decompress time/TPC-H l_comment chunked 191552575 / 190412227 / +0.6%
arrow-ipc decompress time/taxi 51063189 / 51474403 / -0.8%
arrow-ipc decompress time/wide table cols=100 chunks=1 rows=1000 316127 / 319082 / -0.9%
arrow-ipc decompress time/wide table cols=100 chunks=50 rows=1000 314911 / 318199 / -1.0%
arrow-ipc decompress time/wide table cols=1000 chunks=1 rows=1000 3679050 / 3573546 / +3.0%
arrow-ipc decompress time/wide table cols=1000 chunks=50 rows=1000 3513284 / 3738872 / -6.0%
arrow-ipc decompress time/wide table cols=10000 chunks=1 rows=1000 36390049 / 35629283 / +2.1%
arrow-ipc decompress time/wide table cols=10000 chunks=50 rows=1000 36902707 / 36157709 / +2.1%
vortex / arrow-ipc / bytes (1.000x ➖, 0↑ 0↓)
name bytes (PR / base / %diff)
arrow-ipc size/Arade 680639722 / 680639722 / +0.0%
arrow-ipc size/Bimbo 3168319202 / 3168319202 / +0.0%
arrow-ipc size/CMSprovider 2394412322 / 2394412322 / +0.0%
arrow-ipc size/Euro2016 359300042 / 359300042 / +0.0%
arrow-ipc size/Food 252069442 / 252069442 / +0.0%
arrow-ipc size/HashTags 700364562 / 700364562 / +0.0%
arrow-ipc size/TPC-H l_comment canonical 1021072290 / 1021072290 / +0.0%
arrow-ipc size/TPC-H l_comment chunked 1021072290 / 1021072290 / +0.0%
arrow-ipc size/taxi 474481242 / 474481242 / +0.0%
arrow-ipc size/wide table cols=100 chunks=1 rows=1000 1231690 / 1231690 / +0.0%
arrow-ipc size/wide table cols=100 chunks=50 rows=1000 1231690 / 1231690 / +0.0%
arrow-ipc size/wide table cols=1000 chunks=1 rows=1000 12312506 / 12312506 / +0.0%
arrow-ipc size/wide table cols=1000 chunks=50 rows=1000 12312506 / 12312506 / +0.0%
arrow-ipc size/wide table cols=10000 chunks=1 rows=1000 123192506 / 123192506 / +0.0%
arrow-ipc size/wide table cols=10000 chunks=50 rows=1000 123192506 / 123192506 / +0.0%

Validity::and of two non-nullable bool validities, such as a nullable array
masked by another, built a lazy Binary(And) that every reader of the validity
evaluated again. Both sides already hold their bits, so AND them word by word
into a bool validity up front.

Masking a nullable i32 column with scattered nulls and counting its nulls
takes 1.36 µs instead of 1.62 µs.

Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1HnweRGxeDWgQwXXM6f5s
Validity::and read both validities' bits on the host to AND them, which
panics for bits held on a device. Take the word-wise AND only when both
validities are host-resident, and keep a lazy conjunction otherwise.

Signed-off-by: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1HnweRGxeDWgQwXXM6f5s

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

changelog/performance A performance improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants