Skip to content

Commit a45bb60

Browse files
feat: DeltaScheme adjustable compression ratio threshold (#8461)
Delta is a more expensive compression scheme to decompress, so using it for a small win in compression since is a bad idea. Set the default to 1.25 ## Summary This PR makes the `DeltaScheme` configurable by allowing users to specify a custom minimum penalized compression ratio threshold, rather than using a hardcoded value. This enables more flexible tuning of when Delta encoding is selected during compression. --------- Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-authored-by: Claude <noreply@anthropic.com>
1 parent f0b8fb9 commit a45bb60

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

vortex-btrblocks/src/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub const ALL_SCHEMES: &[&dyn Scheme] = &[
4343
&integer::IntRLEScheme,
4444
// Prefer all other schemes above delta, for now (since its slower to decompress).
4545
#[cfg(feature = "unstable_encodings")]
46-
&integer::DeltaScheme,
46+
&integer::DeltaScheme::new(1.25),
4747
////////////////////////////////////////////////////////////////////////////////////////////////
4848
// Float schemes.
4949
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -186,7 +186,7 @@ impl BtrBlocksCompressorBuilder {
186186
// Delta has no GPU decode kernel and its prefix-sum decode is inherently sequential, so it
187187
// is incompatible with pure-GPU decompression paths.
188188
#[cfg(feature = "unstable_encodings")]
189-
excluded.push(integer::DeltaScheme.id());
189+
excluded.push(integer::DeltaScheme::default().id());
190190
let builder = self.exclude_schemes(excluded);
191191

192192
#[cfg(all(feature = "zstd", feature = "unstable_encodings"))]

vortex-btrblocks/src/schemes/integer/delta.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,29 @@ use crate::SchemeExt;
3434
/// Delta replaces each value with its difference from an earlier value (at the FastLanes lane
3535
/// stride), so a later cascade layer (FoR / BitPacking) packs the smaller residuals. It only
3636
/// pays off when those residuals span meaningfully fewer bits than the values themselves.
37-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
38-
pub struct DeltaScheme;
37+
///
38+
/// The minimum penalized compression ratio required for Delta to be selected is configurable via
39+
/// [`DeltaScheme::new`]; [`DeltaScheme::default`] uses a ratio of `1.25`.
40+
#[derive(Debug, Copy, Clone, PartialEq)]
41+
pub struct DeltaScheme {
42+
min_ratio: f64,
43+
}
44+
45+
impl DeltaScheme {
46+
/// Creates a Delta scheme requiring `min_ratio` (after the [`DELTA_PENALTY`]) before it wins.
47+
///
48+
/// Pass a higher ratio to make Delta more conservative, or a lower one to select it more
49+
/// eagerly. [`DeltaScheme::default`] uses a ratio of `1.25`.
50+
pub const fn new(min_ratio: f64) -> Self {
51+
Self { min_ratio }
52+
}
53+
}
54+
55+
impl Default for DeltaScheme {
56+
fn default() -> Self {
57+
Self::new(1.25)
58+
}
59+
}
3960

4061
/// Multiplicative penalty applied to Delta's estimated compression ratio.
4162
///
@@ -65,7 +86,7 @@ impl Scheme for DeltaScheme {
6586
/// bases and the deltas children so we never delta-encode data that was already delta-encoded.
6687
fn descendant_exclusions(&self) -> Vec<DescendantExclusion> {
6788
vec![DescendantExclusion {
68-
excluded: DeltaScheme.id(),
89+
excluded: self.id(),
6990
children: ChildSelection::All,
7091
}]
7192
}
@@ -110,8 +131,9 @@ impl Scheme for DeltaScheme {
110131

111132
// Estimating Delta needs the real transposed-delta span, so defer to a callback that
112133
// delta-encodes the array and measures the residual range.
134+
let min_ratio = self.min_ratio;
113135
CompressionEstimate::Deferred(DeferredEstimate::Callback(Box::new(
114-
|_compressor, data, best_so_far, _ctx, exec_ctx| {
136+
move |_compressor, data, best_so_far, _ctx, exec_ctx| {
115137
let primitive = data.array().clone().execute::<PrimitiveArray>(exec_ctx)?;
116138
let full_width = primitive.ptype().bit_width() as f64;
117139

@@ -138,7 +160,7 @@ impl Scheme for DeltaScheme {
138160
};
139161

140162
let ratio = full_width / delta_bits * DELTA_PENALTY;
141-
if ratio <= 1.0 {
163+
if ratio <= min_ratio {
142164
return Ok(EstimateVerdict::Skip);
143165
}
144166
Ok(EstimateVerdict::Ratio(ratio))

0 commit comments

Comments
 (0)