Fix Validity::mask_eq semantics for mixed variants#8334
Conversation
…ulls The boolean returned by no_nulls() only proves the absence of nulls for the NonNullable and AllValid variants; a Validity::Array may still resolve to all-valid once executed. As validity arrays become lazy this distinction matters, so the cheap check is renamed to definitely_no_nulls() and documented as conservative. For call sites that need a definitive answer, add execute_no_nulls(), which executes the validity into a Mask via execute_mask(). The CUDA ListView export ensure-check is switched to the exact variant since a false answer there is a hard error rather than a slow path. https://claude.ai/code/session_01VPQ7dfZtijfrsjAipwXvEj Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Merging this PR will improve performance by 11.93%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | bitwise_not_vortex_buffer_mut[128] |
273.6 ns | 244.4 ns | +11.93% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing claude/cool-bardeen-l8jlsy-2-mask-eq (afb8906) with develop (b94291b)
Polar Signals Profiling ResultsLatest Run
Powered by Polar Signals Cloud |
Benchmarks: PolarSignals ProfilingVortex (geomean): 0.973x ➖ How to read Verdict and Engines
datafusion / vortex-file-compressed (0.973x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: FineWeb NVMeVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.237x ❌, 0↑ 9↓)
datafusion / vortex-compact (1.233x ❌, 0↑ 9↓)
datafusion / parquet (1.225x ❌, 0↑ 9↓)
duckdb / vortex-file-compressed (1.265x ❌, 0↑ 9↓)
duckdb / vortex-compact (1.252x ❌, 0↑ 9↓)
duckdb / parquet (1.166x ❌, 0↑ 8↓)
File Size Changes (1 files changed, -0.0% overall, 0↑ 1↓)
Totals:
|
Benchmarks: TPC-H SF=1 on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.013x ➖, 0↑ 0↓)
datafusion / vortex-compact (1.006x ➖, 0↑ 0↓)
datafusion / parquet (0.999x ➖, 1↑ 1↓)
datafusion / arrow (1.019x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed (1.004x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.000x ➖, 0↑ 0↓)
duckdb / parquet (1.002x ➖, 1↑ 1↓)
duckdb / duckdb (1.007x ➖, 0↑ 0↓)
File Size Changes (9 files changed, -0.1% overall, 2↑ 7↓)
Totals:
|
Benchmarks: TPC-DS SF=1 on NVMEVerdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.213x ❌, 0↑ 92↓)
datafusion / vortex-compact (1.184x ❌, 0↑ 83↓)
datafusion / parquet (1.197x ❌, 1↑ 87↓)
duckdb / vortex-file-compressed (1.191x ❌, 0↑ 88↓)
duckdb / vortex-compact (1.164x ❌, 0↑ 67↓)
duckdb / parquet (1.124x ❌, 0↑ 59↓)
duckdb / duckdb (1.134x ❌, 0↑ 60↓)
File Size Changes (6 files changed, +0.0% overall, 4↑ 2↓)
Totals:
|
Benchmarks: FineWeb S3Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.026x ➖, 1↑ 2↓)
datafusion / vortex-compact (0.767x ➖, 3↑ 0↓)
datafusion / parquet (1.219x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed (0.956x ➖, 0↑ 2↓)
duckdb / vortex-compact (0.922x ➖, 1↑ 0↓)
duckdb / parquet (0.971x ➖, 0↑ 0↓)
|
…lid in-case the Array was all true Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Benchmarks: Statistical and Population GeneticsVerdict: No clear signal (low confidence) How to read Verdict and Engines
duckdb / vortex-file-compressed (1.014x ➖, 0↑ 0↓)
duckdb / vortex-compact (0.995x ➖, 0↑ 0↓)
duckdb / parquet (0.995x ➖, 0↑ 0↓)
File Size Changes (1 files changed, -0.0% overall, 0↑ 1↓)
Totals:
|
72a9118 to
897128e
Compare
Benchmarks: Random AccessVortex (geomean): 0.718x ✅ How to read Verdict and Engines
unknown / unknown (0.813x ✅, 44↑ 0↓)
|
Benchmarks: TPC-H SF=10 on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.003x ➖, 0↑ 0↓)
datafusion / vortex-compact (1.004x ➖, 0↑ 0↓)
datafusion / parquet (1.006x ➖, 0↑ 0↓)
datafusion / arrow (1.006x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed (1.009x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.000x ➖, 0↑ 0↓)
duckdb / parquet (1.002x ➖, 0↑ 0↓)
duckdb / duckdb (1.006x ➖, 0↑ 0↓)
File Size Changes (27 files changed, -0.0% overall, 16↑ 11↓)
Totals:
|
Benchmarks: Clickbench on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (0.929x ➖, 8↑ 1↓)
datafusion / parquet (0.935x ➖, 4↑ 0↓)
duckdb / vortex-file-compressed (0.953x ➖, 6↑ 1↓)
duckdb / parquet (0.974x ➖, 1↑ 0↓)
duckdb / duckdb (0.955x ➖, 2↑ 0↓)
File Size Changes (104 files changed, -0.0% overall, 47↑ 57↓)
Totals:
|
|
shall we just remove mask_eq? |
Benchmarks: TPC-H SF=1 on S3Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.427x ❌, 0↑ 12↓)
datafusion / vortex-compact (1.110x ➖, 0↑ 6↓)
datafusion / parquet (1.210x ➖, 3↑ 9↓)
duckdb / vortex-file-compressed (1.016x ➖, 0↑ 1↓)
duckdb / vortex-compact (1.049x ➖, 0↑ 0↓)
duckdb / parquet (1.041x ➖, 0↑ 0↓)
|
| Validity::NonNullable | Validity::AllValid, | ||
| ) | ||
| | (Validity::AllInvalid, Validity::AllInvalid) => Ok(true), | ||
| _ => Ok(self.execute_mask(length, ctx)? == other.execute_mask(length, ctx)?), |
There was a problem hiding this comment.
What's the difference between execute_mask and execute::<Mask>?
There was a problem hiding this comment.
if the former is preferable, seems like removing the ability to do execute::<Mask> is also desirable here
There was a problem hiding this comment.
Mask::execute_mask tried to avoid using the ArrayRef::execute loop. I think we want both.
Benchmarks: Appian on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.360x ❌, 0↑ 8↓)
datafusion / parquet (1.342x ❌, 0↑ 8↓)
duckdb / vortex-file-compressed (1.319x ❌, 0↑ 8↓)
duckdb / parquet (1.297x ❌, 0↑ 8↓)
duckdb / duckdb (1.244x ❌, 0↑ 8↓)
File Size Changes (4 files changed, -0.0% overall, 2↑ 2↓)
Totals:
|
Benchmarks: CompressionVortex (geomean): 1.001x ➖ How to read Verdict and Engines
unknown / unknown (0.983x ➖, 5↑ 2↓)
|
Benchmarks: TPC-H SF=10 on S3Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (0.980x ➖, 1↑ 1↓)
datafusion / vortex-compact (0.991x ➖, 1↑ 4↓)
datafusion / parquet (1.003x ➖, 3↑ 2↓)
duckdb / vortex-file-compressed (0.972x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.034x ➖, 0↑ 0↓)
duckdb / parquet (0.932x ➖, 0↑ 0↓)
|
3542eaf to
afb8906
Compare
Summary
PR 2 of a 4-PR stack (stacked on #8333) preparing
Validityfor lazy validity arrays.mask_eqpreviously returnedfalsefor any mixed-variant pairing without executing — e.g. aValidity::Arraythat resolves to all-true compared againstValidity::AllValid. With lazy validity arrays, unresolvedArrayvariants frequently hold constant masks, making this silently wrong rather than merely conservative.