Skip to content

Compare primitive values with RowFn - #9979

Draft
connortsui20 wants to merge 2 commits into
developfrom
ct/row-fn-compare-primitive
Draft

connortsui20 wants to merge 2 commits into
developfrom
ct/row-fn-compare-primitive

Conversation

@connortsui20

@connortsui20 connortsui20 commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Depends on #10014.

Summary

Moves primitive comparisons onto RowFn so decoding, constants, validity, and packed Boolean output use the shared row executor.

Changes

PrimitiveCompare dispatches primitive types and comparison operators through multiversioned RowVisitor::visit_bool, replacing the primitive lane kernels and their operand wrapper. Float comparisons retain Vortex's total ordering.

Depends on #10014 for execution-allocator ownership of Boolean output. The comparison tests added in #9948 are retained and now exercise the RowFn implementation.

Validation before the rebase: 168 focused comparison, mask, and RowFn tests passed on the combined stack, including comparison_uses_execution_allocator, along with cargo clippy -p vortex-array --all-targets --all-features -- -D warnings. Tests, formatting, and benchmarks were not rerun locally after the rebase.

@connortsui20 connortsui20 added the changelog/performance A performance improvement label Sep 22, 2026
@codspeed

codspeed Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 5.81%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ 12 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 12 improved benchmarks
❌ 33 regressed benchmarks
✅ 2138 untouched benchmarks
⏩ 359 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Simulation filter_powerlaw_by_mostly_true[250000] 103.3 µs 149 µs -30.67%
❌ WallTime compare_u8_avx512 1.5 µs 1.9 µs -22.19%
❌ Simulation take[routing/same_chunk/primitive/nonnull/chunks=32/indices=1000] 181.6 µs 224 µs -18.92%
❌ WallTime compare_u8_neon 1.9 µs 2.3 µs -18.34%
❌ Simulation int_gt[16] 94.6 µs 115 µs -17.72%
❌ WallTime compare_u8_avx2 1.6 µs 1.9 µs -16.51%
❌ WallTime lt_i64_nullable_avx512 2.6 µs 3.1 µs -16.31%
❌ Simulation int_gt[1024] 99.8 µs 118.7 µs -15.92%
❌ Simulation or_chain[16] 308.2 µs 365.5 µs -15.68%
❌ Simulation float_gt[16] 215.2 µs 252.3 µs -14.73%
❌ Simulation bench_compare_primitive[(10000, 2)] 65.3 µs 76.4 µs -14.53%
❌ Simulation or_chain[1024] 321.3 µs 375 µs -14.32%
❌ Simulation float_gt[1024] 240.2 µs 280.1 µs -14.22%
❌ Simulation i64_random[256] 4.3 ms 5 ms -14.11%
❌ Simulation i64_lt[true] 80.8 µs 93.7 µs -13.8%
❌ Simulation i64_lt[false] 80.7 µs 93.6 µs -13.76%
❌ Simulation i64_random_chunked[256] 15.9 ms 18.3 ms -13.51%
❌ Simulation baseline_lt[4, 1024] 70.7 µs 81.7 µs -13.44%
❌ Simulation bench_compare_sliced_dict_primitive[(3333, 10000)] 74 µs 84.8 µs -12.69%
❌ Simulation is_not_null_pred[1024] 188.8 µs 216.2 µs -12.66%
... ... ... ... ... ...

ℹ️ 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-compare-primitive (32ce8ba) with develop (c1043b3)

Open in CodSpeed

Footnotes

  1. 359 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 marked this pull request as draft September 22, 2026 19:43
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from 28d9dd8 to cd4b46c Compare September 23, 2026 20:46
@connortsui20
connortsui20 changed the base branch from develop to ct/all-valid-mask-reduction September 23, 2026 20:46
@connortsui20
connortsui20 added this pull request to stack #10017 September 23, 2026 20:46
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from cd4b46c to 6830c56 Compare September 23, 2026 21:01
@connortsui20
connortsui20 removed this pull request from stack #10017 September 23, 2026 21:02
@connortsui20
connortsui20 added this pull request to stack #10019 September 23, 2026 21:02
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from 6830c56 to 8594ed8 Compare September 23, 2026 21:06
@connortsui20
connortsui20 removed this pull request from stack #10019 September 23, 2026 21:19
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from 8594ed8 to cce1488 Compare September 23, 2026 21:19
@connortsui20
connortsui20 added this pull request to stack #10021 September 23, 2026 21:19
@connortsui20
connortsui20 removed this pull request from stack #10021 September 23, 2026 21:23
@connortsui20
connortsui20 changed the base branch from ct/all-valid-mask-reduction to develop September 23, 2026 21:23
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from cce1488 to 0823a7d Compare September 23, 2026 21:23
@connortsui20
connortsui20 changed the base branch from develop to ct/row-fn-output-allocator September 23, 2026 21:23
@connortsui20
connortsui20 added this pull request to stack #10022 September 23, 2026 21:23
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from 0823a7d to f2db74e Compare September 23, 2026 21:26
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from f2db74e to a600c93 Compare September 23, 2026 21:53
connortsui20 added a commit that referenced this pull request Sep 24, 2026
## Summary

Allows lazy masks to attach directly as validity when an encoding can
inspect validity through metadata and the input is `AllValid` or
`NonNullable`. Array-backed validity and encodings that have not opted
in retain the existing lazy-mask fallback.

The reduction rule, in pseudocode, is:

```text
Mask(Array(values, validity = AllValid), m)
    -> Array(values, validity = m)

Mask(Array(values, validity = NonNullable), m)
    -> Array(values, validity = m)
```

This applies when the input encoding opts into
`VALIDITY_IS_METADATA_ONLY` and supports mask reduction. `m` is a
non-nullable Boolean array with the same length as the input, and it may
be lazy. The reduction reuses the values and attaches `m` as validity
without executing it. The output dtype is nullable.

The identity is `AllValid AND m = m`, so no intermediate validity array
is needed.

## Changes

Adds `MaskReduce::VALIDITY_IS_METADATA_ONLY`, defaulting to false, and
enables it for Boolean, primitive, decimal, string, list, struct, map,
and ByteBool encodings. String, decimal, and list reducers preserve
existing buffers and children when rebuilding. List-view masking also
preserves its metadata without revalidating the zero-copy flag.

Two focused tests cover direct attachment to an all-valid primitive
array and the fallback for array-backed validity, including an all-true
bitmap. Existing constant-mask tests remain unchanged, and all tests
stay inline. The Boolean device-buffer fix landed in #10018.

Validation before the rebase: 168 focused comparison, mask, and RowFn
tests passed on the combined stack through #9979, along with `cargo
clippy -p vortex-array --all-targets --all-features -- -D warnings`. The
rebase preserves this PR's patches. Tests, formatting, and benchmarks
were not rerun locally after the rebase.

---------

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from a600c93 to 8eb8c0c Compare September 24, 2026 02:37
Base automatically changed from ct/row-fn-output-allocator to develop September 24, 2026 21:44
connortsui20 added a commit that referenced this pull request Sep 24, 2026
Depends on #10016.

RowFn output payloads bypass the execution allocator. This change
allocates them directly through `ctx.allocator()` across owned,
deferred-retry, selected, filtered, constant, and sink execution, while
preserving zero-copy primitive publication and empty-output paths.

`OutputElement` chooses its collection storage through an associated
buffer type and an allocation hook. The executor writes through
`OutputBuffer` slots, and the buffer implementation constructs the
array. Vortex primitive and Boolean implementations use `BufferMut`,
while scalar and fixed-size-list sinks use the same storage contract.
UTF-8 descriptors, external bytes, and polygon payloads also use the
execution allocator. Physical sink parameters remain separate from
allocation resources.

Regressions check ownership of returned payloads using canonical inputs
prepared before allocation tracking, including a context override,
constant UTF-8 output, retry execution, and zero-copy reuse. A
zero-sized output with `Vec` storage exercises the owned execution paths
without requiring `BufferMut`. Boolean collector selection is preserved.

The Boolean dense-retry path from merged #9986 also uses the execution
allocator, with coverage in the existing packed-output allocator test.

Validation before the rebase: 168 focused comparison, mask, and RowFn
tests passed on the combined stack through #9979, along with `cargo
clippy -p vortex-array --all-targets --all-features -- -D warnings`.
Tests, formatting, and benchmarks were not rerun locally after the
rebase.

---------

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/row-fn-compare-primitive branch from 8eb8c0c to c2e7937 Compare September 24, 2026 21:48
@github-actions

Copy link
Copy Markdown
Contributor

This PR has been marked as stale because it has been open for 14 days with no activity. Please comment or remove the stale label if you wish to keep it active, otherwise it will be closed in 7 days

@github-actions github-actions Bot added the stale This PR is stale and will be auto-closed soon label Oct 10, 2026
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@robert3005 robert3005 removed the stale This PR is stale and will be auto-closed soon label Oct 11, 2026
@robert3005
robert3005 force-pushed the ct/row-fn-compare-primitive branch from c2e7937 to 048a785 Compare October 11, 2026 23:38
Profiling the compare benchmarks against the previous lane kernels showed
that the RowFn row loop is at parity (an optimal vpcmp + kmov loop), and the
regression is per-call batch bookkeeping. This removes the cheap parts of it:

- Attach validity directly to a canonical dense kernel output instead of
  wrapping it in a lazy Mask scalar function that the caller must execute
  again.
- Pass the comparison operands as borrowed execution args instead of
  allocating a Vec and cloning both arrays.
- Collect batch inputs and their dtypes in one loop without a Result
  collect.
- Skip the all-valid probe for a kernel output whose dtype is non-nullable.

Signed-off-by: Claude <noreply@anthropic.com>

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

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.

3 participants