feat(pco): support 8-bit integers - #9582
Conversation
Polar Signals Profiling ResultsLatest Run
Powered by Polar Signals Cloud |
Polar Signals Profiling ResultsLatest Run
Powered by Polar Signals Cloud |
Benchmarks: PolarSignals Profiling 📖Commits: PR datafusion / vortex-file-compressed / ns (1.016x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: String Encoding 📖Commits: PR vortex / vortex-file-compressed / ms (0.996x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / % (1.000x ➖, 0↑ 0↓)
|
Benchmarks: TPC-H SF=1 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.006x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.007x ➖, 0↑ 0↓)
datafusion / parquet / ns (1.002x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (0.991x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.020x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.003x ➖, 0↑ 0↓)
File Size Changes (4 files changed, -0.3% overall, 0↑ 4↓)
Totals:
|
Benchmarks: FineWeb NVMe 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.011x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.962x ➖, 2↑ 0↓)
datafusion / parquet / ns (0.999x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.025x ➖, 0↑ 1↓)
duckdb / vortex-compact / ns (1.003x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.009x ➖, 0↑ 0↓)
No file size changes detected. |
Benchmarks: Clickbench Sorted on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.114x ❌, 0↑ 2↓)
datafusion / vortex-compact / ns (0.945x ➖, 2↑ 0↓)
datafusion / parquet / ns (1.005x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.006x ➖, 0↑ 1↓)
duckdb / vortex-compact / ns (0.961x ➖, 2↑ 0↓)
duckdb / parquet / ns (1.017x ➖, 0↑ 0↓)
File Size Changes (200 files changed, -0.3% overall, 59↑ 141↓)
Totals:
|
Benchmarks: Statistical and Population Genetics 📖Commits: PR How to read Verdict and Engines
duckdb / vortex-file-compressed / ns (1.031x ➖, 1↑ 3↓)
duckdb / vortex-compact / ns (0.996x ➖, 3↑ 3↓)
duckdb / parquet / ns (0.997x ➖, 0↑ 0↓)
File Size Changes (1 files changed, -0.0% overall, 0↑ 1↓)
Totals:
|
Benchmarks: Appian on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-compact / ns (0.997x ➖, 0↑ 0↓)
datafusion / parquet / ns (0.999x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (0.999x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.009x ➖, 0↑ 0↓)
File Size Changes (13 files changed, -63.8% overall, 1↑ 12↓)
Totals:
|
Benchmarks: FineWeb S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.081x ➖, 0↑ 1↓)
datafusion / vortex-compact / ns (1.059x ➖, 0↑ 1↓)
datafusion / parquet / ns (0.939x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (0.984x ➖, 0↑ 0↓)
duckdb / vortex-compact / ns (1.004x ➖, 0↑ 0↓)
duckdb / parquet / ns (1.578x ❌, 0↑ 5↓)
|
Benchmarks: TPC-DS SF=1 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.998x ➖, 1↑ 0↓)
datafusion / vortex-compact / ns (0.993x ➖, 3↑ 0↓)
datafusion / parquet / ns (1.002x ➖, 0↑ 1↓)
duckdb / vortex-file-compressed / ns (1.002x ➖, 1↑ 5↓)
duckdb / vortex-compact / ns (0.994x ➖, 6↑ 4↓)
duckdb / parquet / ns (0.989x ➖, 6↑ 4↓)
File Size Changes (12 files changed, -0.0% overall, 3↑ 9↓)
Totals:
|
Benchmarks: TPC-H SF=10 on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (1.000x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (1.022x ➖, 0↑ 2↓)
datafusion / parquet / ns (0.998x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.004x ➖, 0↑ 1↓)
duckdb / vortex-compact / ns (1.015x ➖, 0↑ 2↓)
duckdb / parquet / ns (0.986x ➖, 1↑ 0↓)
File Size Changes (5 files changed, -0.3% overall, 0↑ 5↓)
Totals:
|
Benchmarks: Clickbench on NVME 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.998x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.996x ➖, 0↑ 0↓)
datafusion / parquet / ns (1.000x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (1.008x ➖, 1↑ 1↓)
duckdb / vortex-compact / ns (0.988x ➖, 1↑ 0↓)
duckdb / parquet / ns (0.999x ➖, 0↑ 0↓)
File Size Changes (100 files changed, -0.1% overall, 10↑ 90↓)
Totals:
|
Benchmarks: Random Access 📖Commits: PR How to read Verdict and Engines
random-access / vortex-file-compressed / ns (0.984x ➖, 1↑ 0↓)
random-access / parquet / ns (0.990x ➖, 0↑ 0↓)
random-access / lance / ns (0.785x ✅, 1↑ 1↓)
|
Benchmarks: TPC-H SF=1 on S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-file-compressed / ns (0.971x ➖, 0↑ 0↓)
datafusion / vortex-compact / ns (0.981x ➖, 1↑ 1↓)
datafusion / parquet / ns (1.030x ➖, 0↑ 0↓)
duckdb / vortex-file-compressed / ns (0.986x ➖, 0↑ 1↓)
duckdb / vortex-compact / ns (1.001x ➖, 0↑ 1↓)
duckdb / parquet / ns (1.006x ➖, 0↑ 0↓)
|
Benchmarks: TPC-H SF=10 on S3 📖Commits: PR How to read Verdict and Engines
datafusion / vortex-compact / ns (0.965x ➖, 1↑ 0↓)
datafusion / parquet / ns (0.930x ➖, 1↑ 0↓)
duckdb / vortex-compact / ns (0.950x ➖, 1↑ 1↓)
duckdb / parquet / ns (0.928x ➖, 1↑ 0↓)
|
e489382 to
72c4f31
Compare
Merging this PR will improve performance by 13.58%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | cold_misaligned[(16, 64)] |
429.1 µs | 377.8 µs | +13.58% |
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/pco-8-bit-missing-ig2d0e (aa4056e) with claude/pco-bump-1.0.3 (acfdede)
Footnotes
-
54 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. ↩
Benchmarks: Compression 📖Commits: PR vortex / vortex-file-compressed / ns (0.979x ➖, 2↑ 0↓)
vortex / vortex-file-compressed / bytes (1.000x ➖, 0↑ 0↓)
vortex / vortex-file-compressed / ratio (0.987x ➖, 2↑ 0↓)
vortex / parquet / ns (0.997x ➖, 0↑ 0↓)
vortex / parquet / bytes (1.000x ➖, 0↑ 0↓)
|
Pco gained u8/i8 support in the 1.0 release, but the Vortex integration still carried the 0.4-era assumption that 8-bit types were unavailable: `number_type_from_ptype` had no I8/U8 arms and would have hit its `unreachable!` arm, and the BtrBlocks integer scheme skipped Pco outright for those ptypes. Map both ptypes onto `NumberType`, which makes the match exhaustive and turns a future ptype addition into a compile error rather than a runtime panic, so the guard call in `PcoData::validate` is no longer needed. Pco additionally refuses 8-bit input unless `enable_8_bit` is set on the `ChunkConfig`, a guard against compressing symbolic data such as UTF-8 text. Vortex only reaches the encoder with numeric primitive arrays, so enable it and leave scheme choice to the compressor's sampling estimate. Dropping the skip lets the compact compressor pick Pco for u8 dictionary codes, where it beats bitpacking on every affected golden entry: int_low_cardinality 6177 -> 5359 bytes string_low_cardinality 8287 -> 7488 bytes binary_low_cardinality 6199 -> 4840 bytes struct_mixed 55986 -> 55187 bytes Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
72c4f31 to
aa4056e
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
Pco gained u8/i8 support in its 1.0 release, but the Vortex integration still carried the earlier assumption that 8-bit types were unavailable:
number_type_from_ptypehad noI8/U8arms and would have hit itsunreachable!arm, and the BtrBlocks integer scheme skipped Pco outright for those ptypes.No dependency change is needed —
ChunkConfig::with_enable_8_bitalready exists in the declaredpco = "1.0.1".Changes
encodings/pco/src/array.rs: mapPType::I8/PType::U8ontoNumberType. This makes the match exhaustive, so a future ptype addition becomes a compile error rather than a runtime panic, and the defensivenumber_type_from_ptypecall inPcoData::validateis no longer needed.enable_8_bitis set on theChunkConfig— a guard against compressing symbolic data such as UTF-8 text. Vortex only reaches the encoder with numeric primitive arrays, so it is enabled and scheme choice is left to the compressor's sampling estimate.vortex-btrblocks/src/schemes/integer/pco.rs: drop theI8 | U8skip.rstestcase per native ptype. Newgradient_u8andnullable_i8columns in the Pco compat fixture.Checks:
cargo test -p vortex-pco -p vortex-btrblocks --all-features(all pass),vortex-compat generate+check --mode exact(29/29),cargo clippy --all-targets --all-featureson the affected crates,cargo +nightly fmt --all. Workspace-wide clippy could not be run here:lance-encodingneedsprotocandvortex-duckdb's build script gets a 403 fetching its tarball, both reproducible on a clean tree.API Changes
Pco now accepts 8-bit primitive arrays where it previously refused them. Dropping the BtrBlocks skip also lets the compact compressor pick Pco for u8 dictionary codes, which changes compressed output in the
with_compactbuilder (golden_defaultis untouched). Four golden snapshots shrink:int_low_cardinalitystring_low_cardinalitybinary_low_cardinalitystruct_mixedWorth a reviewer's judgement: the estimator behind
DeferredEstimate::Sampleis size-only, and dictionary codes are a hot decode path, so this trades bytes for decode speed there. Pco is also unfusable invortex-cuda's plan builder (plan_builder.rs:768), so dict-code subtrees that werefastlanes.bitpackedwill fall off the GPU path. If that trade is unwanted, the 8-bit column support can be kept while guarding the scheme against dictionary code children instead.