Skip to content

Execute primitive numeric operators with RowFn - #9345

Draft
connortsui20 wants to merge 5 commits into
ct/row-fn-frameworkfrom
ct/row-fn-numeric-operators
Draft

Execute primitive numeric operators with RowFn#9345
connortsui20 wants to merge 5 commits into
ct/row-fn-frameworkfrom
ct/row-fn-numeric-operators

Conversation

@connortsui20

@connortsui20 connortsui20 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Rationale for this change

Makes primitive arithmetic the first production user of RowFn. Binary keeps its registered identity and existing scalar-function hooks.

What changes are included in this PR?

Checked add, subtract, and multiply reduce compact failure evidence outside their vector loops. Integer division stops at the first failure and writes directly into uninitialized output. Decimal arithmetic remains on its existing columnar path.

Rust 1.97.1 and LLVM 22.1.6 measurements used one CGU, fat LTO, and target-cpu=native. Large per-row-by-per-row add, subtract, and multiply range from 2.7% faster to 4.8% slower. LLVM 22 does not vectorize the mixed-constant add and subtract loops: those cases are 4.6–5.2x slower, and the existing mul_i32_constant case is 7.5x slower. This is documented as a compiler limitation rather than hidden by framework plumbing.

What APIs are changed? Are there any user-facing changes?

There are no public API changes. Primitive arithmetic delegates execution to the private NumericBinary row kernel.

@connortsui20 connortsui20 changed the title ct/row fn numeric operators Execute primitive numeric operators with RowFn Aug 11, 2026
@codspeed-hq

codspeed-hq Bot commented Aug 11, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 16.25%

⚡ 1 improved benchmark
❌ 29 regressed benchmarks
✅ 1932 untouched benchmarks
🆕 25 new benchmarks
⏩ 89 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation mul_i32_constant 363.2 µs 688 µs -47.2%
Simulation sub_i64_constant 636.7 µs 964.7 µs -34%
Simulation add_i64_constant 636.7 µs 955.1 µs -33.33%
Simulation compact_sliced[(16384, 10)] 1.4 ms 2 ms -28.12%
Simulation compact_sliced[(4096, 10)] 386.8 µs 527.9 µs -26.73%
Simulation search_index_in_range_chunked 5.4 ms 6.4 ms -16.34%
Simulation multipolygon_random_nulls 769.1 µs 919.1 µs -16.32%
Simulation two_vertex_lines 279.9 µs 333.3 µs -16%
Simulation multipolygon_non_nullable 1 ms 1.2 ms -15.21%
Simulation multipolygon_mixed_validity 972.8 µs 1,143.2 µs -14.9%
Simulation list_i32_large 214.9 µs 252 µs -14.7%
Simulation scalar_subtract 11.7 ms 13.7 ms -14.63%
Simulation mul_u8_nonnull 163.2 µs 190.6 µs -14.39%
Simulation nullable_two_vertex_lines 332 µs 386 µs -13.98%
Simulation take_filter_list_slice_mask_random_indices[768, 50] 208.3 µs 238.2 µs -12.57%
Simulation take_filter_list_small_uncached_random_mask_random_indices[256, 10] 203.4 µs 231.2 µs -12.06%
Simulation take_filter_list_random_mask_sequential_indices[768, 50] 205.7 µs 233.6 µs -11.94%
Simulation take_filter_list_slice_mask_random_indices[256, 50] 206.8 µs 234.9 µs -11.94%
Simulation take_filter_list_small_random_mask_random_indices[256, 10] 203.1 µs 230.6 µs -11.91%
Simulation take_filter_list_small_random_mask_random_indices[768, 10] 211.4 µs 239.5 µs -11.76%
... ... ... ... ... ...

ℹ️ 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 ct/row-fn-numeric-operators (f108cdd) with ct/row-fn-framework (58c9e85)

Open in CodSpeed

Footnotes

  1. 89 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@connortsui20
connortsui20 force-pushed the ct/row-fn-numeric-operators branch from ab0697a to b63ded4 Compare August 11, 2026 16:04
@connortsui20
connortsui20 marked this pull request as ready for review August 11, 2026 16:05
@connortsui20
connortsui20 marked this pull request as draft August 11, 2026 16:24
connortsui20 added a commit that referenced this pull request Aug 11, 2026
## Rationale for this change

Lets indexed lane sources return borrowed or otherwise non-`Copy` items.
RowFn needs this for typed row inputs without adding a second kernel
abstraction.

- Progress towards: #9129

## What changes are included in this PR?

Removes the `Copy` bound from `IndexedSource::Item`. It also makes
`LaneZip` fields private, validates lengths once in `LaneZip::new`, and
removes the repeated assertion from its inline `len` method.

This is a prerequisite only. The first production RowFn adopter is in
#9345, so there is no meaningful RowFn performance comparison at this
layer.

## What APIs are changed? Are there any user-facing changes?

`LaneZip` must now be constructed with `LaneZip::new` instead of tuple
syntax. The workspace has no direct field construction outside this
module.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/row-fn-numeric-operators branch 2 times, most recently from e0e1c45 to f8670a8 Compare August 11, 2026 17:35
Route primitive numeric kernels through RowFn while retaining Binary as the public scalar function identity.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/row-fn-numeric-operators branch from f8670a8 to f108cdd Compare August 11, 2026 19:36
@connortsui20

Copy link
Copy Markdown
Member Author

Here are the local arithmetic benchmark results from the final Rust 1.97.1 run.

The comparison used a develop baseline with benchmark-only backfills (1edd0fca) and the full RowFn stack (8ca9fc73). Later stack layers do not change the primitive arithmetic source, but unrelated code-placement effects can still affect these binaries.

The machine was an AMD Ryzen 9 7950X running Linux. The build used rustc 1.97.1, LLVM 22.1.6, one CGU, fat LTO, and -C target-cpu=native. Each target used two warm runs and seven alternating measured pairs. Each process used 100 samples with a 0.25–0.5 second measurement window on CPU 4.

Negative changes are faster. The values are medians across the seven paired runs.

The main results are:

  • Large per-row add, subtract, and multiply range from 2.67% faster to 4.84% slower.
  • Large mixed-constant multiply improves by 18.66–19.46%.
  • LLVM 22 does not vectorize the large mixed-constant add and subtract loops. These cases are 4.62–5.22x slower.
  • mul_i32_constant is 7.46x slower for the same LLVM 22 code-generation problem.
  • Small batches expose the fixed cost of RowFn dispatch and output construction.

A separate comparison covered the later naming and structural cleanup. All 24 RowFn matrix cases remained between 2.59% faster and 1.09% slower.

RowFn arithmetic matrix: 24 cases
Operator Rows Inputs Baseline RowFn Change
Add 128 per-row × per-row 672.2 ns 879.7 ns +30.87%
Add 128 per-row × constant 687.2 ns 1.499 µs +116.56%
Add 128 constant × per-row 739.7 ns 1.519 µs +105.35%
Add 128 per-row × nullable constant 729.7 ns 1.799 µs +146.54%
Add 32,768 per-row × per-row 7.029 µs 7.309 µs +4.84%
Add 32,768 per-row × constant 4.599 µs 22.820 µs +395.76%
Add 32,768 constant × per-row 4.619 µs 24.120 µs +421.76%
Add 32,768 per-row × nullable constant 4.609 µs 23.150 µs +402.27%
Subtract 128 per-row × per-row 667.2 ns 859.7 ns +28.85%
Subtract 128 per-row × constant 682.2 ns 1.499 µs +118.79%
Subtract 128 constant × per-row 729.7 ns 1.519 µs +109.54%
Subtract 128 per-row × nullable constant 694.7 ns 1.809 µs +160.84%
Subtract 32,768 per-row × per-row 7.149 µs 7.319 µs +3.28%
Subtract 32,768 per-row × constant 4.639 µs 22.130 µs +377.04%
Subtract 32,768 constant × per-row 4.639 µs 23.570 µs +407.87%
Subtract 32,768 per-row × nullable constant 4.649 µs 22.450 µs +382.90%
Multiply 128 per-row × per-row 754.7 ns 929.7 ns +23.19%
Multiply 128 per-row × constant 794.7 ns 1.499 µs +91.03%
Multiply 128 constant × per-row 839.7 ns 1.519 µs +81.12%
Multiply 128 per-row × nullable constant 794.7 ns 1.809 µs +126.37%
Multiply 32,768 per-row × per-row 24.790 µs 24.140 µs -2.67%
Multiply 32,768 per-row × constant 29.280 µs 23.570 µs -19.41%
Multiply 32,768 constant × per-row 29.310 µs 23.580 µs -19.46%
Multiply 32,768 per-row × nullable constant 29.280 µs 23.870 µs -18.66%
Existing arithmetic cases and controls: 28 cases
Benchmark Baseline RowFn stack Change
mul_i32_constant 3.609 µs 26.910 µs +645.64%
add_i64_constant 4.499 µs 22.780 µs +406.33%
sub_i64_constant 4.819 µs 22.260 µs +361.92%
mul_i8_nonnull 1.789 µs 1.959 µs +9.45%
mul_i16_nonnull 2.409 µs 2.599 µs +7.89%
mul_u8_nonnull 1.849 µs 1.999 µs +7.53%
mul_u16_nonnull 2.149 µs 2.319 µs +7.45%
add_i32_nonnull 3.569 µs 3.739 µs +5.04%
mul_i32_nonnull 4.099 µs 4.309 µs +4.89%
mul_u32_nonnull 3.649 µs 3.839 µs +4.40%
add_u32_nonnull 3.609 µs 3.739 µs +3.61%
add_i64_nonnull 6.459 µs 6.659 µs +3.08%
and_bool_nullable 2.019 µs 2.069 µs +2.46%
mul_i32_nullable 4.969 µs 5.049 µs +1.40%
div_i64_nonnull 44.730 µs 44.900 µs +0.34%
mul_decimal_i128_nullable 63.420 µs 63.610 µs +0.27%
lt_i64_nullable 4.709 µs 4.719 µs +0.21%
add_decimal_i128_nullable 121.200 µs 121.400 µs +0.17%
mul_decimal_i64_nonnull 16.100 µs 16.120 µs +0.12%
add_decimal_i64_nonnull 65.620 µs 65.590 µs +0.05%
div_decimal_i64_nonnull 63.960 µs 63.960 µs +0.02%
add_i64_nullable 7.449 µs 7.449 µs -0.27%
div_decimal_i128_nullable 166.600 µs 165.900 µs -0.36%
eq_i64_constant 2.719 µs 2.709 µs -0.37%
or_bool_constant 869.7 ns 859.7 ns -1.15%
mul_i64_nonnull 24.680 µs 23.970 µs -2.80%
mul_u64_nonnull 19.300 µs 18.640 µs -3.42%
div_i64_nullable not present 40.610 µs candidate only

div_i64_nullable was new in the candidate inventory, so it has no paired develop result.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant