Skip to content

Commit 3f0df6f

Browse files
authored
perf: sort window rows in place (#376)
1 parent c19209e commit 3f0df6f

11 files changed

Lines changed: 243 additions & 147 deletions

File tree

src/binder/window.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::errors::DatabaseError;
1818
use crate::expression::visitor_mut::{walk_mut_expr, ExprVisitorMut};
1919
use crate::expression::window::{WindowCall, WindowFunction, WindowFunctionKind, WindowSpec};
2020
use crate::expression::ScalarExpression;
21-
use crate::planner::operator::sort::{SortField, SortOperator};
21+
use crate::planner::operator::sort::SortField;
2222
use crate::planner::operator::window::WindowOperator;
2323
use crate::planner::operator::Operator;
2424
use crate::planner::{Childrens, LogicalPlan, PlanArena};
@@ -208,26 +208,16 @@ impl<T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'_, '_, T, A>
208208
}
209209

210210
for group in groups {
211-
let sort_fields = group
212-
.partition_by
213-
.iter()
214-
.cloned()
215-
.map(SortField::from)
216-
.chain(group.order_by.iter().cloned())
217-
.collect::<Vec<_>>();
218-
if !sort_fields.is_empty() {
219-
children = LogicalPlan::new(
220-
Operator::Sort(SortOperator {
221-
sort_fields,
222-
limit: None,
223-
}),
224-
Childrens::Only(Box::new(children)),
225-
);
226-
}
211+
let partition_by_len = group.partition_by.len();
227212
children = LogicalPlan::new(
228213
Operator::Window(WindowOperator {
229-
partition_by: group.partition_by,
230-
order_by: group.order_by,
214+
sort_fields: group
215+
.partition_by
216+
.into_iter()
217+
.map(SortField::from)
218+
.chain(group.order_by)
219+
.collect(),
220+
partition_by_len,
231221
functions: group.functions,
232222
output_columns: group.output_columns,
233223
}),

src/execution/dql/sort.rs

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::types::tuple::Tuple;
2323
use bumpalo::Bump;
2424
use std::cmp::Ordering;
2525
use std::mem::{self, transmute, MaybeUninit};
26+
use std::ops::{Deref, DerefMut};
2627

2728
pub(crate) type BumpVec<'bump, T> = bumpalo::collections::Vec<'bump, T>;
2829

@@ -51,17 +52,35 @@ impl<'a, T> NullableVec<'a, T> {
5152
}
5253

5354
#[inline]
54-
pub(crate) fn into_iter(self) -> impl Iterator<Item = T> + 'a {
55-
self.0
56-
.into_iter()
57-
.map(|item| unsafe { item.assume_init_read() })
55+
pub(crate) fn pop(&mut self) -> Option<T> {
56+
self.0.pop().map(|item| unsafe { item.assume_init() })
57+
}
58+
59+
pub(crate) fn truncate(&mut self, len: usize) {
60+
while self.len() > len {
61+
self.pop();
62+
}
5863
}
5964
}
6065

61-
pub(crate) fn sort_tuples<'a>(
66+
impl<T> Deref for NullableVec<'_, T> {
67+
type Target = [T];
68+
69+
fn deref(&self) -> &Self::Target {
70+
unsafe { std::slice::from_raw_parts(self.0.as_ptr().cast(), self.0.len()) }
71+
}
72+
}
73+
74+
impl<T> DerefMut for NullableVec<'_, T> {
75+
fn deref_mut(&mut self) -> &mut Self::Target {
76+
unsafe { std::slice::from_raw_parts_mut(self.0.as_mut_ptr().cast(), self.0.len()) }
77+
}
78+
}
79+
80+
pub(crate) fn sort_tuples(
6281
sort_fields: &[SortField],
63-
mut tuples: NullableVec<'a, (usize, Tuple)>,
64-
) -> Result<impl Iterator<Item = Tuple> + 'a, DatabaseError> {
82+
tuples: &mut NullableVec<'_, (usize, Tuple)>,
83+
) -> Result<(), DatabaseError> {
6584
let fn_nulls_first = |nulls_first: bool| {
6685
if nulls_first {
6786
Ordering::Greater
@@ -114,12 +133,12 @@ pub(crate) fn sort_tuples<'a>(
114133
});
115134
drop(eval_values);
116135

117-
Ok(tuples.into_iter().map(|(_, tuple)| tuple))
136+
Ok(())
118137
}
119138

120139
pub struct Sort {
121-
output: Option<Box<dyn Iterator<Item = Tuple>>>,
122-
arena: Box<Bump>,
140+
rows: NullableVec<'static, (usize, Tuple)>,
141+
_arena: Box<Bump>,
123142
sort_fields: Vec<SortField>,
124143
limit: Option<usize>,
125144
input: ExecId,
@@ -136,9 +155,15 @@ impl<'a, T: Transaction + 'a> ReadExecutor<'a, T> for Sort {
136155
transaction: &T,
137156
) -> ExecId {
138157
let input = build_read(arena, plan_arena, input, cache, transaction);
158+
let sort_arena = Box::<Bump>::default();
159+
let rows = unsafe {
160+
transmute::<NullableVec<'_, (usize, Tuple)>, NullableVec<'static, (usize, Tuple)>>(
161+
NullableVec::new(&sort_arena),
162+
)
163+
};
139164
arena.push(ExecNode::Sort(Sort {
140-
output: None,
141-
arena: Box::<Bump>::default(),
165+
rows,
166+
_arena: sort_arena,
142167
sort_fields,
143168
limit,
144169
input,
@@ -152,31 +177,23 @@ impl<'a, T: Transaction + 'a> ExecutorNode<'a, T> for Sort {
152177
arena: &mut ExecArena<'a, T>,
153178
plan_arena: &mut crate::planner::PlanArena<'a>,
154179
) -> Result<(), DatabaseError> {
155-
if self.output.is_none() {
156-
let mut tuples = NullableVec::new(&self.arena);
157-
180+
loop {
181+
if let Some((_, tuple)) = self.rows.pop() {
182+
arena.produce_tuple(tuple);
183+
return Ok(());
184+
}
158185
while arena.next_tuple(self.input, plan_arena)? {
159-
let offset = tuples.len();
160-
tuples.put((offset, mem::take(arena.result_tuple_mut())));
186+
let offset = self.rows.len();
187+
self.rows.put((offset, mem::take(arena.result_tuple_mut())));
161188
}
162-
163-
let limit = self.limit.unwrap_or(tuples.len());
164-
let rows = sort_tuples(&self.sort_fields, tuples)?;
165-
// The arena lives at a stable boxed address, so we can keep the iterator
166-
// and resume it across executor polls.
167-
self.output = Some(unsafe {
168-
transmute::<Box<dyn Iterator<Item = Tuple> + '_>, Box<dyn Iterator<Item = Tuple>>>(
169-
Box::new(rows.take(limit)),
170-
)
171-
});
172-
}
173-
174-
if let Some(tuple) = self.output.as_mut().and_then(std::iter::Iterator::next) {
175-
arena.produce_tuple(tuple);
176-
} else {
177-
arena.finish();
189+
if self.rows.is_empty() {
190+
arena.finish();
191+
return Ok(());
192+
}
193+
sort_tuples(&self.sort_fields, &mut self.rows)?;
194+
self.rows.truncate(self.limit.unwrap_or(self.rows.len()));
195+
self.rows.reverse();
178196
}
179-
Ok(())
180197
}
181198
}
182199

@@ -192,6 +209,17 @@ mod test {
192209
use crate::types::LogicalType;
193210
use bumpalo::Bump;
194211

212+
fn sorted_rows<'a>(
213+
sort_fields: &[SortField],
214+
mut tuples: NullableVec<'a, (usize, Tuple)>,
215+
) -> Result<impl Iterator<Item = Tuple> + 'a, DatabaseError> {
216+
sort_tuples(sort_fields, &mut tuples)?;
217+
Ok(tuples.0.into_iter().map(|item| {
218+
let (_, tuple) = unsafe { item.assume_init() };
219+
tuple
220+
}))
221+
}
222+
195223
#[test]
196224
fn test_single_value_desc_and_null_first() -> Result<(), DatabaseError> {
197225
let table_arena = crate::planner::TableArenaCell::default();
@@ -295,19 +323,19 @@ mod test {
295323
}
296324
};
297325

298-
fn_asc_and_nulls_first_eq(Box::new(sort_tuples(
326+
fn_asc_and_nulls_first_eq(Box::new(sorted_rows(
299327
&fn_sort_fields(true, true),
300328
fn_tuples(),
301329
)?));
302-
fn_asc_and_nulls_last_eq(Box::new(sort_tuples(
330+
fn_asc_and_nulls_last_eq(Box::new(sorted_rows(
303331
&fn_sort_fields(true, false),
304332
fn_tuples(),
305333
)?));
306-
fn_desc_and_nulls_first_eq(Box::new(sort_tuples(
334+
fn_desc_and_nulls_first_eq(Box::new(sorted_rows(
307335
&fn_sort_fields(false, true),
308336
fn_tuples(),
309337
)?));
310-
fn_desc_and_nulls_last_eq(Box::new(sort_tuples(
338+
fn_desc_and_nulls_last_eq(Box::new(sorted_rows(
311339
&fn_sort_fields(false, false),
312340
fn_tuples(),
313341
)?));
@@ -525,19 +553,19 @@ mod test {
525553
}
526554
};
527555

528-
fn_asc_1_and_nulls_first_1_and_asc_2_and_nulls_first_2_eq(Box::new(sort_tuples(
556+
fn_asc_1_and_nulls_first_1_and_asc_2_and_nulls_first_2_eq(Box::new(sorted_rows(
529557
&fn_sort_fields(true, true, true, true),
530558
fn_tuples(),
531559
)?));
532-
fn_asc_1_and_nulls_last_1_and_asc_2_and_nulls_first_2_eq(Box::new(sort_tuples(
560+
fn_asc_1_and_nulls_last_1_and_asc_2_and_nulls_first_2_eq(Box::new(sorted_rows(
533561
&fn_sort_fields(true, false, true, true),
534562
fn_tuples(),
535563
)?));
536-
fn_desc_1_and_nulls_first_1_and_asc_2_and_nulls_first_2_eq(Box::new(sort_tuples(
564+
fn_desc_1_and_nulls_first_1_and_asc_2_and_nulls_first_2_eq(Box::new(sorted_rows(
537565
&fn_sort_fields(false, true, true, true),
538566
fn_tuples(),
539567
)?));
540-
fn_desc_1_and_nulls_last_1_and_asc_2_and_nulls_first_2_eq(Box::new(sort_tuples(
568+
fn_desc_1_and_nulls_last_1_and_asc_2_and_nulls_first_2_eq(Box::new(sorted_rows(
541569
&fn_sort_fields(false, false, true, true),
542570
fn_tuples(),
543571
)?));

0 commit comments

Comments
 (0)