Skip to content

Commit 01811c4

Browse files
committed
Make Delta selection ratio a DeltaScheme constructor parameter
Move the minimum penalized compression ratio from a module constant onto DeltaScheme as a field, configurable via DeltaScheme::new(min_ratio). DeltaScheme::default() / DeltaScheme::DEFAULT use DEFAULT_MIN_RATIO (1.25). The static scheme registry uses the const DEFAULT so it stays usable in const context. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent 5782d27 commit 01811c4

2 files changed

Lines changed: 42 additions & 14 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::DEFAULT,
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: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,42 @@ 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 [`DeltaScheme::DEFAULT_MIN_RATIO`].
40+
#[derive(Debug, Copy, Clone, PartialEq)]
41+
pub struct DeltaScheme {
42+
min_ratio: f64,
43+
}
44+
45+
impl DeltaScheme {
46+
/// Default minimum penalized compression ratio for Delta selection.
47+
///
48+
/// Delta only wins when its penalized ratio clears this threshold; otherwise we skip it in
49+
/// favor of simpler, randomly-accessible encodings. The bar is set above `1.0` so we avoid
50+
/// picking Delta for marginal gains that do not justify breaking random access and the
51+
/// prefix-sum decode pass.
52+
pub const DEFAULT_MIN_RATIO: f64 = 1.25;
53+
54+
/// A [`DeltaScheme`] using [`DEFAULT_MIN_RATIO`](Self::DEFAULT_MIN_RATIO).
55+
///
56+
/// Usable in const contexts (e.g. the static scheme registry) where [`Default`] cannot run.
57+
pub const DEFAULT: Self = Self::new(Self::DEFAULT_MIN_RATIO);
58+
59+
/// Creates a Delta scheme requiring `min_ratio` (after the [`DELTA_PENALTY`]) before it wins.
60+
///
61+
/// Pass a higher ratio to make Delta more conservative, or a lower one to select it more
62+
/// eagerly. [`DeltaScheme::default`] uses [`DEFAULT_MIN_RATIO`](Self::DEFAULT_MIN_RATIO).
63+
pub const fn new(min_ratio: f64) -> Self {
64+
Self { min_ratio }
65+
}
66+
}
67+
68+
impl Default for DeltaScheme {
69+
fn default() -> Self {
70+
Self::DEFAULT
71+
}
72+
}
3973

4074
/// Multiplicative penalty applied to Delta's estimated compression ratio.
4175
///
@@ -48,13 +82,6 @@ const DELTA_PENALTY: f64 = 0.95;
4882
/// Minimum length before Delta is worth considering (one FastLanes chunk).
4983
const MIN_DELTA_LEN: usize = 1024;
5084

51-
/// Minimum estimated compression ratio (after the [`DELTA_PENALTY`]) for Delta to be selected.
52-
///
53-
/// Delta only wins when its penalized ratio clears this threshold; otherwise we skip it in favor
54-
/// of simpler, randomly-accessible encodings. Raising the bar avoids picking Delta for marginal
55-
/// gains that do not justify breaking random access and the prefix-sum decode pass.
56-
const MIN_DELTA_RATIO: f64 = 1.25;
57-
5885
impl Scheme for DeltaScheme {
5986
fn scheme_name(&self) -> &'static str {
6087
"vortex.int.delta"
@@ -72,7 +99,7 @@ impl Scheme for DeltaScheme {
7299
/// bases and the deltas children so we never delta-encode data that was already delta-encoded.
73100
fn descendant_exclusions(&self) -> Vec<DescendantExclusion> {
74101
vec![DescendantExclusion {
75-
excluded: DeltaScheme.id(),
102+
excluded: self.id(),
76103
children: ChildSelection::All,
77104
}]
78105
}
@@ -117,8 +144,9 @@ impl Scheme for DeltaScheme {
117144

118145
// Estimating Delta needs the real transposed-delta span, so defer to a callback that
119146
// delta-encodes the array and measures the residual range.
147+
let min_ratio = self.min_ratio;
120148
CompressionEstimate::Deferred(DeferredEstimate::Callback(Box::new(
121-
|_compressor, data, best_so_far, _ctx, exec_ctx| {
149+
move |_compressor, data, best_so_far, _ctx, exec_ctx| {
122150
let primitive = data.array().clone().execute::<PrimitiveArray>(exec_ctx)?;
123151
let full_width = primitive.ptype().bit_width() as f64;
124152

@@ -145,7 +173,7 @@ impl Scheme for DeltaScheme {
145173
};
146174

147175
let ratio = full_width / delta_bits * DELTA_PENALTY;
148-
if ratio <= MIN_DELTA_RATIO {
176+
if ratio <= min_ratio {
149177
return Ok(EstimateVerdict::Skip);
150178
}
151179
Ok(EstimateVerdict::Ratio(ratio))

0 commit comments

Comments
 (0)