Skip to content

Commit 6087918

Browse files
committed
feat: add list min and max expressions
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
1 parent 3975895 commit 6087918

10 files changed

Lines changed: 1589 additions & 0 deletions

File tree

vortex-array/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ harness = false
255255
name = "list_sum"
256256
harness = false
257257

258+
[[bench]]
259+
name = "list_min_max"
260+
harness = false
261+
258262
[[bench]]
259263
name = "listview_rebuild"
260264
harness = false
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
//! Benchmarks for primitive `list_min` and `list_max` over `List`, `ListView`, and
5+
//! `FixedSizeList` inputs.
6+
7+
#![expect(clippy::cast_possible_truncation)]
8+
#![expect(clippy::unwrap_used)]
9+
10+
use std::sync::LazyLock;
11+
12+
use divan::Bencher;
13+
use vortex_array::ArrayRef;
14+
use vortex_array::Canonical;
15+
use vortex_array::IntoArray;
16+
use vortex_array::VortexSessionExecute;
17+
use vortex_array::arrays::BoolArray;
18+
use vortex_array::arrays::FixedSizeListArray;
19+
use vortex_array::arrays::ListArray;
20+
use vortex_array::arrays::ListViewArray;
21+
use vortex_array::arrays::PrimitiveArray;
22+
use vortex_array::expr::list_max;
23+
use vortex_array::expr::list_min;
24+
use vortex_array::expr::root;
25+
use vortex_array::validity::Validity;
26+
use vortex_buffer::Buffer;
27+
use vortex_session::VortexSession;
28+
29+
fn main() {
30+
divan::main();
31+
}
32+
33+
static SESSION: LazyLock<VortexSession> = LazyLock::new(vortex_array::array_session);
34+
35+
const BENCH_ARGS: &[(usize, usize)] = &[(8_192, 10), (8_192, 100), (8_192, 1_000)];
36+
37+
fn elements(num_lists: usize, list_size: usize) -> ArrayRef {
38+
PrimitiveArray::from_option_iter(
39+
(0..num_lists * list_size)
40+
.map(|index| (index % 10 != 0).then_some(((index * 31) % 10_007) as i32)),
41+
)
42+
.into_array()
43+
}
44+
45+
fn list_validity(num_lists: usize) -> Validity {
46+
Validity::Array(BoolArray::from_iter((0..num_lists).map(|index| index % 10 != 0)).into_array())
47+
}
48+
49+
fn make_list(num_lists: usize, list_size: usize) -> ArrayRef {
50+
let offsets: Buffer<i32> = (0..=num_lists)
51+
.map(|index| (index * list_size) as i32)
52+
.collect();
53+
ListArray::try_new(
54+
elements(num_lists, list_size),
55+
offsets.into_array(),
56+
list_validity(num_lists),
57+
)
58+
.unwrap()
59+
.into_array()
60+
}
61+
62+
fn make_listview(num_lists: usize, list_size: usize) -> ArrayRef {
63+
let offsets: Buffer<i32> = (0..num_lists)
64+
.map(|index| (((index * 17) % num_lists) * (list_size - 1)) as i32)
65+
.collect();
66+
let sizes: Buffer<i32> = std::iter::repeat_n(list_size as i32, num_lists).collect();
67+
ListViewArray::new(
68+
elements(num_lists, list_size),
69+
offsets.into_array(),
70+
sizes.into_array(),
71+
list_validity(num_lists),
72+
)
73+
.into_array()
74+
}
75+
76+
fn make_fixed_size_list(num_lists: usize, list_size: usize) -> ArrayRef {
77+
FixedSizeListArray::new(
78+
elements(num_lists, list_size),
79+
list_size as u32,
80+
list_validity(num_lists),
81+
num_lists,
82+
)
83+
.into_array()
84+
}
85+
86+
fn run_vortex(bencher: Bencher, array: ArrayRef, minimum: bool) {
87+
let expression = if minimum {
88+
list_min(root())
89+
} else {
90+
list_max(root())
91+
};
92+
bencher
93+
.with_inputs(|| (&array, SESSION.create_execution_ctx()))
94+
.bench_refs(|(array, ctx)| {
95+
array
96+
.clone()
97+
.apply(&expression)
98+
.unwrap()
99+
.execute::<Canonical>(ctx)
100+
.unwrap()
101+
});
102+
}
103+
104+
#[divan::bench(args = BENCH_ARGS)]
105+
fn vortex_list_min(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
106+
run_vortex(bencher, make_list(num_lists, list_size), true);
107+
}
108+
109+
#[divan::bench(args = BENCH_ARGS)]
110+
fn vortex_list_max(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
111+
run_vortex(bencher, make_list(num_lists, list_size), false);
112+
}
113+
114+
#[divan::bench(args = BENCH_ARGS)]
115+
fn vortex_listview_min(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
116+
run_vortex(bencher, make_listview(num_lists, list_size), true);
117+
}
118+
119+
#[divan::bench(args = BENCH_ARGS)]
120+
fn vortex_listview_max(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
121+
run_vortex(bencher, make_listview(num_lists, list_size), false);
122+
}
123+
124+
#[divan::bench(args = BENCH_ARGS)]
125+
fn vortex_fixed_size_list_min(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
126+
run_vortex(bencher, make_fixed_size_list(num_lists, list_size), true);
127+
}
128+
129+
#[divan::bench(args = BENCH_ARGS)]
130+
fn vortex_fixed_size_list_max(bencher: Bencher, (num_lists, list_size): (usize, usize)) {
131+
run_vortex(bencher, make_fixed_size_list(num_lists, list_size), false);
132+
}

0 commit comments

Comments
 (0)