Skip to content

Commit ed766e0

Browse files
committed
Optimize primitive arg layout fast paths
1 parent 912663b commit ed766e0

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

core-relations/src/action/mod.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,34 @@ impl Bindings {
279279
}
280280
}
281281

282+
fn single_external_borrowed_window(
283+
instrs: &[Instr],
284+
) -> Option<(ExternalFunctionId, Variable, usize, Variable)> {
285+
match instrs {
286+
[
287+
Instr::External {
288+
func,
289+
args,
290+
dst,
291+
},
292+
] => {
293+
let mut start = None;
294+
for (idx, arg) in args.iter().enumerate() {
295+
let QueryEntry::Var(v) = arg else {
296+
return None;
297+
};
298+
if idx == 0 {
299+
start = Some(*v);
300+
} else if v.index() != start?.index() + idx {
301+
return None;
302+
}
303+
}
304+
start.map(|start| (*func, start, args.len(), *dst))
305+
}
306+
_ => None,
307+
}
308+
}
309+
282310
/// A binding that has been extracted from a [`Bindings`] struct via the [`Bindings::take`] method.
283311
///
284312
/// This allows for a variable's contents to be read while the [`Bindings`] struct has been
@@ -603,6 +631,33 @@ impl ExecutionState<'_> {
603631
bindings.matches = 1;
604632
}
605633

634+
if let Some((func, start, len, dst)) = single_external_borrowed_window(instrs) {
635+
let matches = bindings.matches;
636+
let mut out: Pooled<Vec<Value>> = with_pool_set(|ps| ps.get());
637+
out.resize(matches, Value::stale());
638+
let mut transposed: Pooled<Vec<Value>> = with_pool_set(|ps| ps.get());
639+
transposed.resize(matches * len, Value::stale());
640+
let start_index = start.index();
641+
let mut succeeded = 0usize;
642+
for row in 0..matches {
643+
for col in 0..len {
644+
transposed[row * len + col] =
645+
bindings[Variable::from_usize(start_index + col)][row];
646+
}
647+
if self.should_stop() {
648+
break;
649+
}
650+
if let Some(value) =
651+
self.call_external_func(func, &transposed[row * len..(row + 1) * len])
652+
{
653+
out[row] = value;
654+
succeeded += 1;
655+
}
656+
}
657+
bindings.insert(dst, &out);
658+
return succeeded;
659+
}
660+
606661
// Vectorized execution for larger batch sizes
607662
let mut mask = with_pool_set(|ps| Mask::new(0..bindings.matches, ps));
608663
for instr in instrs {

core-relations/src/action/tests.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{
22
action::mask::{IterResult, ValueSource},
3+
free_join::Variable,
4+
numeric_id::NumericId,
35
pool::{PoolSet, with_pool_set},
46
};
57

@@ -148,3 +150,37 @@ fn test_early_stop_multiple_clones() {
148150
assert!(state2.should_stop());
149151
assert!(state3.should_stop());
150152
}
153+
154+
#[test]
155+
fn run_instrs_single_external_borrowed_window_executes() {
156+
let mut db = crate::free_join::Database::default();
157+
let sum = db.add_external_function(Box::new(crate::make_external_func(|_, args| {
158+
let [x, y] = args else { panic!() };
159+
Some(crate::common::Value::from_usize(
160+
(x.rep() + y.rep()) as usize,
161+
))
162+
})));
163+
let mut state = crate::action::ExecutionState::new(db.read_only_view(), Default::default());
164+
let mut bindings = super::Bindings::new(8);
165+
bindings.insert(
166+
Variable::from_usize(0),
167+
&[crate::table_shortcuts::v(1), crate::table_shortcuts::v(2)],
168+
);
169+
bindings.insert(
170+
Variable::from_usize(1),
171+
&[crate::table_shortcuts::v(10), crate::table_shortcuts::v(20)],
172+
);
173+
174+
let instrs = vec![super::Instr::External {
175+
func: sum,
176+
args: vec![Variable::from_usize(0).into(), Variable::from_usize(1).into()],
177+
dst: Variable::from_usize(2),
178+
}];
179+
180+
let succeeded = state.run_instrs(&instrs, &mut bindings);
181+
assert_eq!(succeeded, 2);
182+
assert_eq!(
183+
&bindings[Variable::from_usize(2)],
184+
&[crate::table_shortcuts::v(11), crate::table_shortcuts::v(22)]
185+
);
186+
}

0 commit comments

Comments
 (0)