Skip to content

Commit fa27422

Browse files
gatesnrobert3005
authored andcommitted
Batch fragmented CASE branches and push selections before scalar execution
Signed-off-by: Nicholas Gates <nick@nickgates.com>
1 parent 3c87da0 commit fa27422

4 files changed

Lines changed: 322 additions & 117 deletions

File tree

‎vortex-array/benches/expr/case_when_bench.rs‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ use vortex_array::IntoArray;
1414
use vortex_array::VortexSessionExecute;
1515
use vortex_array::array_session;
1616
use vortex_array::arrays::BoolArray;
17+
use vortex_array::arrays::ConstantArray;
18+
use vortex_array::arrays::DecimalArray;
19+
use vortex_array::arrays::ScalarFnArray;
1720
use vortex_array::arrays::StructArray;
21+
use vortex_array::arrays::VarBinViewArray;
22+
use vortex_array::builtins::ArrayBuiltins;
23+
use vortex_array::dtype::DecimalDType;
1824
use vortex_array::expr::case_when;
1925
use vortex_array::expr::case_when_no_else;
2026
use vortex_array::expr::eq;
@@ -24,6 +30,12 @@ use vortex_array::expr::lit;
2430
use vortex_array::expr::lt;
2531
use vortex_array::expr::nested_case_when;
2632
use vortex_array::expr::root;
33+
use vortex_array::scalar::Scalar;
34+
use vortex_array::scalar_fn::ScalarFnVTableExt;
35+
use vortex_array::scalar_fn::fns::case_when::CaseWhen;
36+
use vortex_array::scalar_fn::fns::case_when::CaseWhenOptions;
37+
use vortex_array::scalar_fn::fns::operators::Operator;
38+
use vortex_array::validity::Validity;
2739
use vortex_buffer::Buffer;
2840
use vortex_session::VortexSession;
2941

@@ -37,6 +49,53 @@ fn main() {
3749
divan::main();
3850
}
3951

52+
#[divan::bench(args = [1, 4, 16, 64, 256, 4096])]
53+
fn case_when_decimal_product(bencher: Bencher, run_length: usize) {
54+
let len = 65_536;
55+
let lhs = DecimalArray::new(
56+
Buffer::from_iter((0..len).map(|i| (i % 10_000) as i64)),
57+
DecimalDType::new(15, 2),
58+
Validity::NonNullable,
59+
)
60+
.into_array();
61+
let rhs = DecimalArray::new(
62+
Buffer::from_iter((0..len).map(|i| (i % 100) as i64)),
63+
DecimalDType::new(15, 2),
64+
Validity::NonNullable,
65+
)
66+
.into_array();
67+
let product = lhs.binary(rhs, Operator::Mul).unwrap();
68+
let otherwise = ConstantArray::new(Scalar::zero_value(product.dtype()), len).into_array();
69+
bench_branches(bencher, run_length, product, otherwise);
70+
}
71+
72+
#[divan::bench(args = [1, 4, 16, 64, 256, 4096])]
73+
fn case_when_string_values(bencher: Bencher, run_length: usize) {
74+
let len = 65_536;
75+
let lhs = VarBinViewArray::from_iter_str((0..len).map(|i| format!("long-left-value-{i}")))
76+
.into_array();
77+
let rhs = VarBinViewArray::from_iter_str((0..len).map(|i| format!("long-right-value-{i}")))
78+
.into_array();
79+
bench_branches(bencher, run_length, lhs, rhs);
80+
}
81+
82+
fn bench_branches(bencher: Bencher, run_length: usize, lhs: ArrayRef, rhs: ArrayRef) {
83+
let mask = BoolArray::from_iter((0..lhs.len()).map(|i| (i / run_length).is_multiple_of(2)))
84+
.into_array();
85+
let array = ScalarFnArray::try_new(
86+
CaseWhen.bind(CaseWhenOptions {
87+
num_when_then_pairs: 1,
88+
has_else: true,
89+
}),
90+
vec![mask, lhs, rhs],
91+
)
92+
.unwrap()
93+
.into_array();
94+
bencher
95+
.with_inputs(|| SESSION.create_execution_ctx())
96+
.bench_refs(|ctx| array.clone().execute::<Canonical>(ctx).unwrap());
97+
}
98+
4099
fn make_struct_array(size: usize) -> ArrayRef {
41100
let data: Buffer<i32> = (0..size as i32).collect();
42101
let field = data.into_array();
@@ -264,7 +323,7 @@ fn case_when_all_false(bencher: Bencher, size: usize) {
264323
});
265324
}
266325

267-
/// Benchmark CASE WHEN cycling through 3 branches per row (triggers merge_row_by_row).
326+
/// Benchmark compact CASE WHEN assembly with three interleaved branches.
268327
/// Run length = 1; exercises branch 0, branch 1, and the else fallback at every 3rd row.
269328
#[divan::bench(args = [100, 400])]
270329
fn case_when_fragmented(bencher: Bencher, size: usize) {

‎vortex-array/src/arrays/scalar_fn/rules.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl ArrayParentReduceRule<ScalarFn> for ScalarFilterPushdownRule {
117117
prepare_mask_for_reuse(values, nchildren);
118118
}
119119

120+
// Selection precedes value evaluation, including errors in unselected rows.
120121
let new_children: Vec<_> = child
121122
.iter_children()
122123
.map(|c| match c.as_opt::<Constant>() {

0 commit comments

Comments
 (0)