Skip to content

Commit bad88ce

Browse files
committed
Add wide decimal byte-part splitting and assembly logic (#9808)
Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
1 parent 46371c3 commit bad88ce

9 files changed

Lines changed: 718 additions & 0 deletions

File tree

‎Cargo.lock‎

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎encodings/decimal-byte-parts/Cargo.toml‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,15 @@ vortex-mask = { workspace = true }
2626
vortex-session = { workspace = true }
2727

2828
[dev-dependencies]
29+
divan = { workspace = true }
30+
rand = { workspace = true }
2931
rstest = { workspace = true }
3032
vortex-array = { path = "../../vortex-array", features = ["_test-harness"] }
33+
34+
[[bench]]
35+
name = "dbp_assemble"
36+
harness = false
37+
38+
[[bench]]
39+
name = "dbp_split"
40+
harness = false
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
//! Shared decimal inputs for splitting and assembly benchmarks.
5+
6+
use rand::RngExt;
7+
use rand::SeedableRng;
8+
use rand::rngs::StdRng;
9+
use vortex_array::arrays::DecimalArray;
10+
use vortex_array::dtype::DecimalDType;
11+
use vortex_array::dtype::DecimalType;
12+
use vortex_array::dtype::i256;
13+
use vortex_array::validity::Validity;
14+
use vortex_buffer::Buffer;
15+
use vortex_error::vortex_panic;
16+
17+
pub(super) fn cases() -> Vec<(DecimalType, usize)> {
18+
[DecimalType::I64, DecimalType::I128, DecimalType::I256]
19+
.into_iter()
20+
.flat_map(|values_type| [1_024, 8_192].map(|len| (values_type, len)))
21+
.collect()
22+
}
23+
24+
pub(super) fn decimal_array(
25+
values_type: DecimalType,
26+
len: usize,
27+
validity: Validity,
28+
) -> DecimalArray {
29+
let mut rng = StdRng::seed_from_u64(42);
30+
31+
macro_rules! decimal {
32+
($T:ty, $precision:literal) => {{
33+
let max = <$T>::pow(10, $precision) - 1;
34+
let values: Buffer<$T> = (0..len).map(|_| rng.random_range(-max..=max)).collect();
35+
DecimalArray::new(values, DecimalDType::new($precision, 2), validity)
36+
}};
37+
}
38+
39+
match values_type {
40+
DecimalType::I64 => decimal!(i64, 18),
41+
DecimalType::I128 => decimal!(i128, 38),
42+
DecimalType::I256 => {
43+
// Keep the magnitude below 10^76 while exercising all four signed/unsigned words.
44+
let values: Buffer<i256> = (0..len)
45+
.map(|_| i256::from_parts(rng.random(), rng.random::<i128>() >> 4))
46+
.collect();
47+
DecimalArray::new(values, DecimalDType::new(76, 2), validity)
48+
}
49+
_ => vortex_panic!("unsupported benchmark storage type: {values_type}"),
50+
}
51+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
//! Reassembling primitive decimal parts across storage widths and lengths.
5+
6+
mod common;
7+
8+
use divan::Bencher;
9+
use divan::black_box;
10+
use vortex_array::VortexSessionExecute;
11+
use vortex_array::array_session;
12+
use vortex_array::arrays::PrimitiveArray;
13+
use vortex_array::dtype::DecimalType;
14+
use vortex_array::validity::Validity;
15+
use vortex_decimal_byte_parts::_benchmarking::assemble_decimal;
16+
use vortex_decimal_byte_parts::split_decimal;
17+
use vortex_error::VortexExpect;
18+
use vortex_error::VortexResult;
19+
20+
use crate::common::cases;
21+
use crate::common::decimal_array;
22+
23+
fn main() {
24+
divan::main();
25+
}
26+
27+
#[divan::bench(args = cases())]
28+
fn dbp_assemble(bencher: Bencher, (values_type, len): (DecimalType, usize)) {
29+
let decimal = decimal_array(values_type, len, Validity::NonNullable);
30+
let mut ctx = array_session().create_execution_ctx();
31+
let parts = split_decimal(&decimal, &mut ctx).vortex_expect("split benchmark input");
32+
let msp = parts
33+
.msp
34+
.execute::<PrimitiveArray>(&mut ctx)
35+
.vortex_expect("execute benchmark MSP");
36+
let lower_parts = parts
37+
.lower_parts
38+
.into_iter()
39+
.map(|part| part.execute::<PrimitiveArray>(&mut ctx))
40+
.collect::<VortexResult<Vec<_>>>()
41+
.vortex_expect("execute benchmark lower parts");
42+
let decimal_dtype = decimal.decimal_dtype();
43+
44+
bencher.bench(|| {
45+
assemble_decimal(black_box(&msp), black_box(&lower_parts), decimal_dtype)
46+
.vortex_expect("assemble decimal byte parts")
47+
});
48+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
//! Splitting decimal arrays across storage widths, lengths, and validity paths.
5+
6+
mod common;
7+
8+
use divan::Bencher;
9+
use divan::black_box;
10+
use rand::RngExt;
11+
use rand::SeedableRng;
12+
use rand::rngs::StdRng;
13+
use vortex_array::VortexSessionExecute;
14+
use vortex_array::array_session;
15+
use vortex_array::dtype::DecimalType;
16+
use vortex_array::validity::Validity;
17+
use vortex_decimal_byte_parts::split_decimal;
18+
use vortex_error::VortexExpect;
19+
20+
use crate::common::cases;
21+
use crate::common::decimal_array;
22+
23+
fn main() {
24+
divan::main();
25+
}
26+
27+
#[divan::bench(args = cases())]
28+
fn dbp_split_all_valid(bencher: Bencher, (values_type, len): (DecimalType, usize)) {
29+
bench_split(bencher, values_type, len, Validity::AllValid);
30+
}
31+
32+
#[divan::bench(args = cases())]
33+
fn dbp_split_mixed_null(bencher: Bencher, (values_type, len): (DecimalType, usize)) {
34+
let mut rng = StdRng::seed_from_u64(42);
35+
let validity = Validity::from_iter((0..len).map(|_| rng.random_bool(0.5)));
36+
bench_split(bencher, values_type, len, validity);
37+
}
38+
39+
fn bench_split(bencher: Bencher, values_type: DecimalType, len: usize, validity: Validity) {
40+
let decimal = decimal_array(values_type, len, validity);
41+
let session = array_session();
42+
bencher
43+
.with_inputs(|| session.create_execution_ctx())
44+
.bench_refs(|ctx| {
45+
split_decimal(black_box(&decimal), ctx).vortex_expect("split decimal array")
46+
});
47+
}

0 commit comments

Comments
 (0)