Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
3e070a6
feat: add native Pco-inspired numeric encodings
lwwmanning Aug 18, 2026
5786fd7
bench: compare FloatMult child codecs
lwwmanning Aug 18, 2026
a20651a
feat: add native FloatMult encoding
lwwmanning Aug 18, 2026
0f79c92
perf: omit zero FloatMult adjustments
lwwmanning Aug 18, 2026
607508b
refactor: focus native float compression prototypes
lwwmanning Aug 18, 2026
d3066bf
perf: optimize and benchmark native float compression
lwwmanning Aug 19, 2026
e721625
perf: validate native float compression schemes
lwwmanning Aug 19, 2026
0cf4f8b
perf: add native block residual selection
lwwmanning Aug 19, 2026
ed9efb1
perf: expand native numeric compression coverage
lwwmanning Aug 19, 2026
c351b9a
bench: profile quotient remainder candidates
lwwmanning Aug 19, 2026
37b7547
bench: estimate bitmap patch alternatives
lwwmanning Aug 19, 2026
27aca12
perf: evaluate native f32 float quant
lwwmanning Aug 19, 2026
4465ba2
perf: fuse float quant with bitpacking
lwwmanning Aug 19, 2026
47daa71
perf: fuse float quant pair decode
lwwmanning Aug 19, 2026
097f9f5
perf: select two-child float quant
lwwmanning Aug 19, 2026
be658d2
perf: specialize block residual decode
lwwmanning Aug 19, 2026
be0b43b
perf: penalize dense block residual patches
lwwmanning Aug 19, 2026
a14aa0c
bench: validate block residual compositions
lwwmanning Aug 19, 2026
e117cee
perf: estimate block residual without payloads
lwwmanning Aug 19, 2026
ace5630
bench: compare narrow residuals with pco
lwwmanning Aug 19, 2026
1c9abba
bench: prototype checkpointed range packing
lwwmanning Aug 19, 2026
c2bb1d3
bench: measure complete fixed-bin trees
lwwmanning Aug 19, 2026
652d9fe
bench: optimize nullable fixed-bin trees
lwwmanning Aug 19, 2026
d417de4
refactor: move RangePacked prototype into encoding crate
lwwmanning Aug 19, 2026
0c663c2
feat: add serialized RangePacked array
lwwmanning Aug 19, 2026
de7da9a
bench: evaluate native pco replacement trees
lwwmanning Aug 19, 2026
e2c3cf6
refactor: remove RangePacked selector experiment
lwwmanning Aug 19, 2026
3d47f2c
bench: isolate numeric file topology costs
lwwmanning Aug 19, 2026
8e2b55f
perf: flatten BlockResidual file layout
lwwmanning Aug 19, 2026
01b5304
bench: compare compact compression
lwwmanning Aug 19, 2026
c26ffb6
bench: serialize compact compression timings
lwwmanning Aug 19, 2026
2c1ac5e
bench: classify remaining compact numeric gaps
lwwmanning Aug 19, 2026
aca7413
bench: preserve latent widths in split estimates
lwwmanning Aug 19, 2026
40903b3
bench: prototype bounded IntMult layouts
lwwmanning Aug 19, 2026
56e013a
bench: evaluate centered block residuals
lwwmanning Aug 19, 2026
940e977
chore: remove rejected centered residual prototype
lwwmanning Aug 19, 2026
7310914
perf: calibrate BlockResidual selection
lwwmanning Aug 19, 2026
1fd7bea
feat: add composable IntMult transform
lwwmanning Aug 20, 2026
ca570c3
perf: fuse base-one dictionary addition
lwwmanning Aug 20, 2026
6713869
docs: update native numeric compression plan
lwwmanning Aug 20, 2026
7d89719
perf: optimize FloatQuant split encoding
lwwmanning Aug 20, 2026
eb3cf3e
feat: complete numeric array type coverage
lwwmanning Aug 20, 2026
9ed1d71
bench: test decomposed fixed-bin trees
lwwmanning Aug 20, 2026
22bc671
bench: compare composable IntMult trees
lwwmanning Aug 20, 2026
f87ac69
bench: test BlockResidual patch positions
lwwmanning Aug 20, 2026
2994eb9
perf: decode unsigned BlockResidual directly
lwwmanning Aug 20, 2026
406b1b5
perf: rank dictionary codes by frequency
lwwmanning Aug 20, 2026
4d483d4
perf: accelerate range-packed float trees
lwwmanning Aug 20, 2026
af23b71
feat: add experimental float range packing
lwwmanning Aug 20, 2026
13b5ca8
perf: reject poor range-packed fits early
lwwmanning Aug 20, 2026
24f9ac2
docs: record broad range-packed results
lwwmanning Aug 20, 2026
06ded43
docs: record ordered range-packed experiment
lwwmanning Aug 20, 2026
380e09c
refactor: specialize ordered range packing
lwwmanning Aug 20, 2026
db9ae2c
perf: calibrate float quant selection
lwwmanning Aug 20, 2026
d182ca9
perf: reject constant range-packed samples
lwwmanning Aug 20, 2026
46ad405
perf: fuse packed IntMult decode
lwwmanning Aug 20, 2026
26c406e
feat: decompose fixed-bin float compression
lwwmanning Aug 20, 2026
f3a338c
bench: report compressed chunk trees
lwwmanning Aug 20, 2026
7708e83
fix: compare fused candidates with cascades
lwwmanning Aug 20, 2026
dd8bf40
bench: cover two-child FloatQuant widths
lwwmanning Aug 20, 2026
ff27e2e
perf: avoid FloatQuant sample packing
lwwmanning Aug 20, 2026
d2565c3
feat: select BlockResidual for 16-bit integers
lwwmanning Aug 20, 2026
a34240e
feat: evaluate 8-bit BlockResidual selection
lwwmanning Aug 20, 2026
28004e2
bench: complete numeric bundle evaluation
lwwmanning Aug 20, 2026
446c323
bench: validate 8-bit BlockResidual selection
lwwmanning Aug 20, 2026
4a393ea
bench: measure 8-bit random access
lwwmanning Aug 20, 2026
f1df252
feat: calibrate 8-bit BlockResidual selection
lwwmanning Aug 20, 2026
3b6eec3
perf: fuse f16 ordered BlockResidual decode
lwwmanning Aug 20, 2026
f85e40b
perf: fuse implicit FloatQuant f64 decode
lwwmanning Aug 20, 2026
be6635e
bench: calibrate wider BlockResidual selection
lwwmanning Aug 20, 2026
2bc86a8
perf: avoid repeated BlockResidual validation
lwwmanning Aug 20, 2026
5cbc73d
bench: map fixed-bin coverage
lwwmanning Aug 21, 2026
b73d5a0
bench: test integer fixed bins under ALP
lwwmanning Aug 21, 2026
d11660c
feat: finalize opportunistic numeric compression
lwwmanning Aug 21, 2026
15e7e6b
refactor: remove unselected IntMult prototype
lwwmanning Aug 21, 2026
2d97dd5
Merge origin/develop into wm/pcodec-fixed-bin-experiment
lwwmanning Aug 21, 2026
c369178
refactor: harden native numeric encodings
lwwmanning Aug 21, 2026
6a23456
docs: remove native compression work log
lwwmanning Aug 21, 2026
815e0ce
fix: stage numeric encodings in preview edition
lwwmanning Aug 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ members = [
"encodings/bytebool",
"encodings/parquet-variant",
"encodings/onpair",
"encodings/block-residual",
"encodings/float-quant",
# Benchmarks
"benchmarks/bench-support",
"benchmarks/lance-bench",
Expand Down Expand Up @@ -97,7 +99,7 @@ rust-version = "1.95"
version = "0.1.0"

[workspace.dependencies]
alp = "0.0.2"
alp = "0.0.3"
anyhow = "1.0.100"
arbitrary = "1.3.2"
arc-swap = "1.9"
Expand Down Expand Up @@ -297,6 +299,7 @@ vortex = { version = "0.1.0", path = "./vortex" }
vortex-alp = { version = "0.1.0", path = "./encodings/alp", default-features = false }
vortex-array = { version = "0.1.0", path = "./vortex-array", default-features = false }
vortex-arrow = { version = "0.1.0", path = "./vortex-arrow", default-features = false }
vortex-block-residual = { version = "0.1.0", path = "./encodings/block-residual", default-features = false }
vortex-btrblocks = { version = "0.1.0", path = "./vortex-btrblocks", default-features = false }
vortex-buffer = { version = "0.1.0", path = "./vortex-buffer", default-features = false }
vortex-bytebool = { version = "0.1.0", path = "./encodings/bytebool", default-features = false }
Expand All @@ -311,6 +314,7 @@ vortex-error = { version = "0.1.0", path = "./vortex-error", default-features =
vortex-fastlanes = { version = "0.1.0", path = "./encodings/fastlanes", default-features = false }
vortex-file = { version = "0.1.0", path = "./vortex-file", default-features = false }
vortex-flatbuffers = { version = "0.1.0", path = "./vortex-flatbuffers", default-features = false }
vortex-float-quant = { version = "0.1.0", path = "./encodings/float-quant", default-features = false }
vortex-fsst = { version = "0.1.0", path = "./encodings/fsst", default-features = false }
vortex-io = { version = "0.1.0", path = "./vortex-io", default-features = false }
vortex-ipc = { version = "0.1.0", path = "./vortex-ipc", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions benchmarks/compress-bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tracing = { workspace = true }
vortex = { workspace = true }
vortex-arrow = { workspace = true }
vortex-bench = { workspace = true }
vortex-btrblocks = { workspace = true }
vortex-cuda = { workspace = true, optional = true }

[features]
Expand Down
20 changes: 20 additions & 0 deletions benchmarks/compress-bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,26 @@ See [`src/main.rs`](./src/main.rs) for the dataset list and CLI flags (`--format
cargo run -p compress-bench --profile release_debug
```

Compare the default compressor, Compact, and Parquet with Zstd:

```bash
cargo run -p compress-bench --profile release_debug -- \
--formats vortex,vortex-compact,parquet
```

Compare a numeric scheme bundle with the same command and one of these values:

- `--vortex-numeric-bundle prior-default`
- `--vortex-numeric-bundle block-residual`
- `--vortex-numeric-bundle current-default`

Add a local Parquet file with `--parquet-path`. Use `--datasets` to select its file stem.

```bash
cargo run -p compress-bench --profile release_debug -- \
--parquet-path /tmp/input.parquet --datasets '^input$'
```

## GPU decompression

`--gpu-decompress` is opt-in, requires the `cuda` feature, and restricts the suite to the
Expand Down
55 changes: 47 additions & 8 deletions benchmarks/compress-bench/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use vortex_bench::Engine;
use vortex_bench::Format;
use vortex_bench::LogFormat;
use vortex_bench::Target;
use vortex_bench::VortexNumericBundle;
use vortex_bench::compress::CompressMeasurements;
use vortex_bench::compress::CompressOp;
use vortex_bench::compress::Compressor;
Expand All @@ -32,6 +33,9 @@ use vortex_bench::compress::benchmark_decompress;
use vortex_bench::compress::calculate_ratios;
use vortex_bench::create_output_writer;
use vortex_bench::datasets::Dataset;
use vortex_bench::datasets::feature_vectors::GloveEmbeddingsData;
use vortex_bench::datasets::feature_vectors::OpenAiEmbeddingsData;
use vortex_bench::datasets::local_parquet::LocalParquetData;
use vortex_bench::datasets::struct_list_of_ints::StructListOfInts;
use vortex_bench::datasets::taxi_data::TaxiData;
use vortex_bench::datasets::tpch_l_comment::TPCHLCommentCanonical;
Expand Down Expand Up @@ -73,6 +77,9 @@ struct Args {
ops: Vec<CompressOp>,
#[arg(long)]
datasets: Option<String>,
/// Add a local Parquet file to the benchmark suite.
#[arg(long)]
parquet_path: Vec<PathBuf>,
/// Print the dataset names that would run, one per line, and exit.
/// Knowledge of datasets lies only in this binary so we need
/// orchestrator to know whan queries to run one by one.
Expand Down Expand Up @@ -111,6 +118,9 @@ struct Args {
ingest_output: Option<PathBuf>,
#[arg(long)]
tracing: bool,
/// Select the numeric scheme bundle for Vortex compression.
#[arg(long, value_enum, default_value_t)]
vortex_numeric_bundle: VortexNumericBundle,
/// Format for the primary stderr log sink. `text` is the default human-readable format;
/// `json` emits one JSON object per event, suitable for piping into `jq`.
#[arg(long, value_enum, default_value_t = LogFormat::Text)]
Expand Down Expand Up @@ -149,13 +159,15 @@ async fn main() -> anyhow::Result<()> {
run_compress(
args.iterations,
args.datasets.map(|d| Regex::new(&d)).transpose()?,
args.parquet_path,
formats,
ops,
mode,
args.print_datasets,
args.display_format,
args.output_path,
args.ingest_output,
args.vortex_numeric_bundle,
)
.await
}
Expand All @@ -182,13 +194,24 @@ impl BenchMode {
}

/// Get a compressor for the given format.
fn get_compressor(format: Format, mode: BenchMode) -> Box<dyn Compressor> {
fn get_compressor(
format: Format,
mode: BenchMode,
vortex_numeric_bundle: VortexNumericBundle,
) -> Box<dyn Compressor> {
if let BenchMode::Gpu(options) = mode {
return gpu_compressor(format, options);
}

match format {
Format::OnDiskVortex => Box::new(VortexCompressor),
Format::OnDiskVortex => Box::new(VortexCompressor::new(
Format::OnDiskVortex,
vortex_numeric_bundle,
)),
Format::VortexCompact => Box::new(VortexCompressor::new(
Format::VortexCompact,
VortexNumericBundle::CurrentDefault,
)),
Format::Parquet => Box::new(ParquetCompressor::new()),
#[cfg(feature = "lance")]
Format::Lance => Box::new(LanceCompressor),
Expand All @@ -209,13 +232,15 @@ const DOC_PATH: &str = "benchmarks/compress-bench/README.md";
async fn run_compress(
iterations: usize,
datasets_filter: Option<Regex>,
parquet_paths: Vec<PathBuf>,
formats: Vec<Format>,
ops: Vec<CompressOp>,
mode: BenchMode,
print_datasets: bool,
display_format: DisplayFormat,
output_path: Option<PathBuf>,
ingest_output: Option<PathBuf>,
vortex_numeric_bundle: VortexNumericBundle,
) -> anyhow::Result<()> {
let targets = formats
.iter()
Expand All @@ -238,6 +263,10 @@ async fn run_compress(
// Some(READ_PROJECTION_COLUMNS),
// ),
];
let local_parquet = parquet_paths
.into_iter()
.map(LocalParquetData::try_new)
.collect::<anyhow::Result<Vec<_>>>()?;

// Datasets run in GPU mode. Add one only after a `--gpu-verify` run has confirmed its CUDA
// decode end to end; a dataset here that cannot decode fails the benchmark job. Between them
Expand All @@ -262,6 +291,8 @@ async fn run_compress(

let all_datasets: Vec<&dyn Dataset> = [
&TaxiData as &dyn Dataset,
&GloveEmbeddingsData,
&OpenAiEmbeddingsData,
PBI_DATASETS.get(Arade),
PBI_DATASETS.get(Bimbo),
PBI_DATASETS.get(CMSprovider),
Expand All @@ -273,13 +304,14 @@ async fn run_compress(
// Hatred, // panic in fsst_compress_iter
// TableroSistemaPenal, // Unexpected type error
// YaleLanguages, // 4th column looks like integer but also contains Y
&TPCHLCommentChunked,
&TPCHLCommentChunked as &dyn Dataset,
&TPCHLCommentCanonical,
&DownloadableDataset::RPlace,
&DownloadableDataset::AirQuality,
]
.into_iter()
.chain(structlistofints.iter().map(|d| d as &dyn Dataset))
.chain(local_parquet.iter().map(|d| d as &dyn Dataset))
.collect();

let datasets: Vec<&dyn Dataset> = if mode.is_gpu() {
Expand Down Expand Up @@ -316,9 +348,16 @@ async fn run_compress(
let survey_all = mode.is_gpu();
let mut failures: Vec<(String, anyhow::Error)> = Vec::new();

for dataset_handle in datasets.into_iter() {
let run =
run_benchmark_for_dataset(&progress, &formats, &ops, iterations, dataset_handle, mode);
for dataset_handle in datasets {
let run = run_benchmark_for_dataset(
&progress,
&formats,
&ops,
iterations,
dataset_handle,
mode,
vortex_numeric_bundle,
);

// Missing CUDA kernel support surfaces as a panic rather than an error, so the survey
// has to catch those too or the first unsupported dataset ends the run.
Expand Down Expand Up @@ -403,6 +442,7 @@ async fn run_benchmark_for_dataset(
iterations: usize,
dataset_handle: &dyn Dataset,
mode: BenchMode,
vortex_numeric_bundle: VortexNumericBundle,
) -> anyhow::Result<(CompressMeasurements, Vec<v3::V3Record>)> {
let bench_name = dataset_handle.name();
// A GPU decode and a host decode of the same dataset would otherwise publish the same
Expand All @@ -427,8 +467,7 @@ async fn run_benchmark_for_dataset(
let mut v3_records: Vec<v3::V3Record> = Vec::new();

for format in formats {
let compressor = get_compressor(*format, mode);

let compressor = get_compressor(*format, mode, vortex_numeric_bundle);
for op in ops {
let time = match op {
CompressOp::Compress => {
Expand Down
Loading
Loading