Conversation
Reuse collect_bool_word for primitive comparison bitmaps while preserving execution-context allocation and comparison semantics. Cover bitmap boundaries, all primitive types, nulls, and constant operand orientation. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Use byte packing only for i8/u8 and preserve the existing lane collectors for wider primitive types. The type selection folds away during monomorphization and avoids the wider AVX2 comparison regressions. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Keep type selection in collect_bits_dispatch and collect_zip_bits_dispatch, with independent narrow collectors and the existing wider collectors. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Limit the new boundary matrix to the i8/u8 specialization. Existing tests cover the unchanged wider primitive comparison paths. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Merging this PR will regress 8 benchmarks
|
Summary
Keep an integer array's logical dtype while storing a narrower integer child. For example, a logical
i64array can hold ani8buffer and compare at that width without widening first.Stacked on #9948, the 8-bit primitive comparison optimization. This draft targets
mk/primitive-compare-bitmap; it adds no further changes to the primitive comparison kernels or their existing benchmarks.Changes
NarrowArray::try_newfor an existing narrow child andNarrowArray::encodefor selecting storage from non-null bounds. Preserve signedness and nullability; flatten nested wrappers.Design · Full benchmark report · All results, quartiles, and per-pass medians
Benchmarks
Apple M5 Max, Rust 1.98.0, 1,048,576 non-null rows. Three interleaved passes of 140 samples per case; pooled medians. All Narrow representations retain logical
i64. Compute starts with prebuilt inputs and excludes encoding.< constant< columnThe i8 comparison gains are 4.4× against a constant and 6.0× against a column. Across individual passes these ratios range from 4.33–4.41× and 6.03–7.02×. Absolute times vary across passes; raw variation is included in the report. Buffer sizes exclude array objects, allocator metadata, and RSS.
Filter selects approximately 50%; take gathers N/8 pseudorandom indices. Every operation executes to its final primitive buffer or boolean bitmap.
Encoding i64 into i8, including a fresh bounds scan, costs 334 µs. The constant-comparison savings amortize this in roughly 3–4 comparisons in this fixture. Widening a full i8 child back to i64 costs 189 µs. One comparison alone does not justify converting an existing wide buffer.
Draft limitations
Validation
cargo nextest run -p vortex-array -p vortex-fastlanes: 4,121 passed, one existing skip.cargo test --doc -p vortex-array: 76 passed, 21 ignored.cargo clippy -p vortex-array -p vortex-fastlanes --all-targets --all-features -- -D warnings: passed.cargo clippy --all-targets --all-features: passed across the workspace.cargo +nightly-2026-09-10 fmt --all --checkandgit diff --check: passed.The workspace build warned that clang-format was unavailable for a generated DuckDB header. No C++ or CUDA sources were changed.