feat: add experimental onpair string encoding#8144
Conversation
Adds the vortex-onpair array encoding under encodings/experimental/onpair, sourcing the compression algorithm from the standalone `onpair` crate (local path dependency) rather than vendored code. - vortex-onpair: Vortex array wrapping, serialisation, and cast/filter pushdown only; train/encode/decode live in the onpair crate. - btrblocks: register OnPairScheme alongside FSSTScheme so the sample-based selector keeps the smaller per column; delta-encode the monotonic dict_offsets/codes_offsets children (>= 2048 rows) when it wins. - vortex-file: register the OnPair encoding and allow it in the write strategy. Note: onpair is a local path dependency for now (to be published to crates.io). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
- Remove unused public DEFAULT_BITS const and config_with_bits fn (plus their public-api.lock entries). - Drop stale "C++" references in comments; the algorithm is the pure-Rust onpair crate, not the old FFI shim. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
onpair string encoding
Merging this PR will degrade performance by 15.06%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | baseline_lt[16, 65536] |
217.4 µs | 303.3 µs | -28.3% |
| ❌ | Simulation | baseline_lt[4, 65536] |
200.7 µs | 258.5 µs | -22.36% |
| ❌ | Simulation | baseline_eq[4, 65536] |
184.9 µs | 237 µs | -21.98% |
| ❌ | Simulation | fast_lt_out_of_range[16, 65536] |
207.9 µs | 235.4 µs | -11.68% |
| ❌ | Simulation | baseline_eq[16, 65536] |
229.7 µs | 259.5 µs | -11.47% |
| ⚡ | Simulation | bitwise_not_vortex_buffer_mut[128] |
304.4 ns | 275.3 ns | +10.6% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing onpair-encoding (7b86a0f) with develop (0e7619b)
Polar Signals Profiling ResultsLatest Run
Previous Runs (11)
Powered by Polar Signals Cloud |
Benchmarks: PolarSignals ProfilingVortex (geomean): 1.023x ➖ How to read Verdict and Engines
datafusion / vortex-file-compressed (1.023x ➖, 0↑ 1↓)
File Size Changes (1 files changed, +0.5% overall, 1↑ 0↓)
Totals:
|
Benchmarks: TPC-H SF=1 on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.064x ➖, 0↑ 4↓)
datafusion / vortex-compact (1.068x ➖, 0↑ 4↓)
datafusion / parquet (1.020x ➖, 1↑ 2↓)
datafusion / arrow (1.048x ➖, 0↑ 2↓)
duckdb / vortex-file-compressed (1.034x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.020x ➖, 0↑ 0↓)
duckdb / parquet (1.028x ➖, 0↑ 1↓)
duckdb / duckdb (1.033x ➖, 0↑ 0↓)
File Size Changes (18 files changed, -5.3% overall, 9↑ 9↓)
Totals:
Full attributed analysis
|
Benchmarks: TPC-DS SF=1 on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.040x ➖, 1↑ 4↓)
datafusion / vortex-compact (1.023x ➖, 0↑ 3↓)
datafusion / parquet (1.043x ➖, 1↑ 11↓)
duckdb / vortex-file-compressed (1.039x ➖, 0↑ 8↓)
duckdb / vortex-compact (1.038x ➖, 0↑ 8↓)
duckdb / parquet (1.037x ➖, 1↑ 3↓)
duckdb / duckdb (1.039x ➖, 0↑ 4↓)
File Size Changes (48 files changed, -0.2% overall, 43↑ 5↓)
Totals:
Full attributed analysis
|
Benchmarks: Statistical and Population GeneticsVerdict: No clear signal (low confidence) How to read Verdict and Engines
duckdb / vortex-file-compressed (0.990x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.002x ➖, 0↑ 0↓)
duckdb / parquet (1.016x ➖, 0↑ 0↓)
File Size Changes (2 files changed, -0.2% overall, 1↑ 1↓)
Totals:
Full attributed analysis
|
Benchmarks: TPC-H SF=10 on NVMEVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (0.982x ➖, 0↑ 0↓)
datafusion / vortex-compact (0.975x ➖, 0↑ 0↓)
datafusion / parquet (0.957x ➖, 0↑ 0↓)
datafusion / arrow (0.961x ➖, 1↑ 0↓)
duckdb / vortex-file-compressed (1.006x ➖, 0↑ 0↓)
duckdb / vortex-compact (0.998x ➖, 0↑ 0↓)
duckdb / parquet (0.970x ➖, 1↑ 0↓)
duckdb / duckdb (1.003x ➖, 0↑ 0↓)
File Size Changes (48 files changed, -5.2% overall, 22↑ 26↓)
Totals:
Full attributed analysis
|
Replace the hand-rolled SIMD decoder (DecodeView::decode_rows_unchecked, build_dict_table) with onpair::decompress_into / decompress_row_into / decompressed_len. OwnedDecodeInputs is now just four flat host buffers plus a Parts<'_, u32> view; the hot loop lives upstream where the aarch64 NEON intrinsic path also lives. Bench (UrlLog, 1M rows): decompress_into median 8.4 ms, canonicalize_to_varbinview 14.7 ms. Adds num-traits as a direct dep to support the generic widen helpers (AsPrimitive::as_() side-steps clippy::cast_* lints on the match_each_integer_ptype! arms). Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
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.216x ➖, 0↑ 4↓)
datafusion / vortex-compact (0.944x ➖, 1↑ 2↓)
datafusion / parquet (1.158x ➖, 0↑ 5↓)
duckdb / vortex-file-compressed (0.930x ➖, 0↑ 0↓)
duckdb / vortex-compact (0.955x ➖, 0↑ 0↓)
duckdb / parquet (0.973x ➖, 0↑ 0↓)
Full attributed analysis
|
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.843x ➖, 3↑ 0↓)
datafusion / vortex-compact (0.919x ➖, 0↑ 0↓)
datafusion / parquet (0.950x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed (0.864x ➖, 0↑ 0↓)
duckdb / vortex-compact (0.882x ➖, 0↑ 0↓)
duckdb / parquet (0.912x ➖, 0↑ 0↓)
Full attributed analysis
|
Benchmarks: FineWeb NVMeVerdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (1.074x ➖, 2↑ 3↓)
datafusion / vortex-compact (0.993x ➖, 0↑ 0↓)
datafusion / parquet (1.005x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed (1.073x ➖, 1↑ 3↓)
duckdb / vortex-compact (1.022x ➖, 0↑ 1↓)
duckdb / parquet (1.002x ➖, 0↑ 0↓)
File Size Changes (2 files changed, -12.0% overall, 1↑ 1↓)
Totals:
Full attributed analysis
|
Benchmarks: FineWeb S3Verdict: No clear signal (low confidence) How to read Verdict and Engines
datafusion / vortex-file-compressed (0.936x ➖, 0↑ 1↓)
datafusion / vortex-compact (0.987x ➖, 0↑ 0↓)
datafusion / parquet (1.062x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed (0.918x ➖, 0↑ 0↓)
duckdb / vortex-compact (1.006x ➖, 0↑ 0↓)
duckdb / parquet (1.043x ➖, 0↑ 0↓)
Full attributed analysis
|
|
fineweb regression are quite small due to like contains and prefix. |
| object_store = { version = "0.13.1", default-features = false } | ||
| once_cell = "1.21" | ||
| oneshot = { version = "0.2.0", features = ["async"] } | ||
| onpair = { version = "0.0.3", git = "https://github.com/spiraldb/onpair.git", rev = "53e8ca6081d377e9933d999cef286e26bf52e2c7" } |
There was a problem hiding this comment.
We can't have git dependencies in the trees of published crates.
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> # Conflicts: # encodings/fastlanes/src/delta/vtable/rules.rs
robert3005
left a comment
There was a problem hiding this comment.
I think the structure makes sense. We will need fuzzer to run over it and audit compute operations
Adds the
vortex-onpairarray encoding underencodings/experimental/onpair, sourcing the compression algorithm from the standaloneonpaircrate (local path dependency) rather than vendored code.