perf: Avoid redundant mask slices - #9268
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
f5aa03d to
47dafff
Compare
Polar Signals Profiling ResultsLatest Run
Previous Runs (1)
Powered by Polar Signals Cloud |
Polar Signals Profiling ResultsLatest Run
Powered by Polar Signals Cloud |
Benchmarks: String Encoding 📖vortex / vortex-file-compressed / ms (1.003x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / % (1.000x ➖, 0↑ 0↓)
|
Benchmarks: Random Access 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
random-access / vortex-file-compressed / ns (0.976x ➖, 0↑ 0↓)
random-access / parquet / ns (1.001x ➖, 0↑ 0↓)
random-access / lance / ns (0.990x ➖, 0↑ 0↓)
|
Benchmarks: Appian on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-compact / ns (0.998x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.989x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (0.994x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.002x ➖, 0↑ 0↓)
File Size Changes (10 files changed, -63.8% overall, 0↑ 10↓)
Totals:
|
Benchmarks: Statistical and Population Genetics 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
duckdb / vortex-file-compressed / ns (1.061x ➖, 1↑ 5↓)
duckdb / vortex-compact / ns (1.063x ➖, 0↑ 3↓)
duckdb / parquet / ns (0.998x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: TPC-H SF=1 on S3 📖Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.914x ➖, 1↑ 0↓)
datafusion / vortex-compact / ns (0.970x ➖, 0↑ 1↓)
datafusion / parquet / ns (0.980x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (0.981x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.002x ➖, 1↑ 0↓)
duckdb / parquet / ns (0.971x ➖, 0↑ 0↓)
|
Benchmarks: TPC-H SF=1 on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.995x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.001x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.987x ➖, 1↑ 1↓)
duckdb / vortex-file-compressed / ns (1.012x ➖, 1↑ 0↓)
duckdb / vortex-compact / ns (0.992x ➖, 1↑ 0↓)
duckdb / parquet / ns (1.002x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: PolarSignals Profiling 📖Vortex (geomean): 0.987x ➖ datafusion / vortex-file-compressed / ns (0.987x ➖, 1↑ 0↓)
File Size Changes (1 files changed, +0.0% overall, 1↑ 0↓)
Totals:
|
Benchmarks: TPC-H SF=10 on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.003x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.997x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.989x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.009x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (0.974x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.000x ➖, 1↑ 0↓)
No file size changes detected. |
Benchmarks: Clickbench Sorted on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.998x ➖, 1↑ 0↓)
datafusion / vortex-compact / ns (1.010x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.962x ➖, 1↑ 0↓)
duckdb / vortex-file-compressed / ns (1.008x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.045x ➖, 0↑ 2↓)
duckdb / parquet / ns (1.001x ➖, 0↑ 0↓)
File Size Changes (200 files changed, +0.0% overall, 103↑ 97↓)
Totals:
|
Benchmarks: FineWeb NVMe 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.042x ➖, 0↑ 1↓)
datafusion / vortex-compact / ns (0.997x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.982x ➖, 1↑ 0↓)
duckdb / vortex-file-compressed / ns (0.988x ➖, 1↑ 1↓)
duckdb / vortex-compact / ns (0.983x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.008x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: TPC-DS SF=1 on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.998x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.007x ➖, 0↑ 3↓)
datafusion / parquet / ns (0.999x ➖, 1↑ 3↓)
duckdb / vortex-file-compressed / ns (1.009x ➖, 3↑ 7↓)
duckdb / vortex-compact / ns (1.018x ➖, 1↑ 8↓)
duckdb / parquet / ns (0.998x ➖, 4↑ 3↓)
No file size changes detected. |
Benchmarks: FineWeb S3 📖Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.130x ➖, 0↑ 2↓)
datafusion / vortex-compact / ns (1.162x ➖, 1↑ 3↓)
datafusion / parquet / ns (1.042x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.029x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (0.964x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.523x ❌, 0↑ 2↓)
|
Benchmarks: Clickbench on NVME 📖Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.989x ➖, 4↑ 3↓)
datafusion / vortex-compact / ns (1.000x ➖, 0↑ 1↓)
datafusion / parquet / ns (1.010x ➖, 0↑ 2↓)
duckdb / vortex-file-compressed / ns (0.979x ➖, 8↑ 4↓)
duckdb / vortex-compact / ns (0.995x ➖, 4↑ 2↓)
duckdb / parquet / ns (0.994x ➖, 1↑ 1↓)
No file size changes detected. |
Benchmarks: TPC-H SF=10 on S3 📖Verdict: No clear signal (environment too noisy confidence) How to read Verdict and Engines
datafusion / vortex-compact / ns (1.039x ➖, 0↑ 2↓)
datafusion / parquet / ns (0.846x ➖, 5↑ 1↓)
duckdb / vortex-compact / ns (0.975x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.042x ➖, 0↑ 1↓)
|
Benchmarks: Compression 📖vortex / vortex-file-compressed / ns (0.985x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / bytes (1.000x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / ratio (0.989x ➖, 0↑ 0↓)
vortex / parquet / ns (1.001x ➖, 0↑ 0↓)
vortex / parquet / bytes (1.000x ➖, 0↑ 0↓)
|
000eadc to
b920a3e
Compare
Splits usually align with chunk boundaries, so a single chunk covers the entire row range and the per-chunk slice is the identity. That identity slice is not free. Mask::slice on a Mask::Values goes through Mask::from_buffer, which re-popcounts the whole buffer to recompute a true_count it already had, and rebuilds MaskValues with empty indices/slices caches. Mask is Arc-backed, so returning a clone keeps the cached representations and costs a refcount bump. MaskFuture::slice allocates a boxed, shared future per call whose only job is to await the inner future and hand the mask back unchanged. Cloning shares the existing one. Add the fast path to both slice methods rather than to the ChunkedReader call sites, so every caller benefits. Mask::Values maintains 0 < true_count < len: all five construction sites return AllTrue/AllFalse for the degenerate counts first. A full-range slice therefore re-derives the same variant, so the clone is equivalent to the general path. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
b920a3e to
feebb84
Compare
|
|
||
| /// Create a MaskFuture that resolves to a slice of the original mask. | ||
| pub fn slice(&self, range: Range<usize>) -> Self { | ||
| // Slicing the whole mask is the identity. Cloning shares the existing future instead of |
Avoid redundant mask slices for Mask and MaskFuture