Skip to content

Commit 72c71d9

Browse files
committed
perf: compute UIContext on prepare
1 parent a3bed5b commit 72c71d9

2 files changed

Lines changed: 50 additions & 32 deletions

File tree

src/launcher/batcher.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use color_eyre::eyre::{Result, ensure};
1+
use color_eyre::eyre::{Result, ensure, eyre};
22

33
use tracing::{debug, info};
44

@@ -115,6 +115,18 @@ impl<Cushion> Default for BatcherState<Cushion> {
115115
}
116116
}
117117

118+
pub struct Prepared<T>(Buffer<(T, usize)>);
119+
120+
impl<T> Prepared<T> {
121+
pub(crate) fn into_inner(self) -> Buffer<(T, usize)> {
122+
self.0
123+
}
124+
125+
pub(crate) fn new(value: Buffer<(T, usize)>) -> Self {
126+
Self(value)
127+
}
128+
}
129+
118130
impl<Cushion, UIContext> Batcher<Cushion, UIContext>
119131
where
120132
Cushion: Send,
@@ -157,16 +169,26 @@ where
157169

158170
/// Prepares the next batch of indices for rendering.
159171
///
160-
/// This asynchronous function generates and returns a `Buffer<usize>` containing indices
172+
/// This asynchronous function generates and returns a `Prepared<UIContext>` containing indices
161173
/// that correspond to UI elements needing rendering. The resulting buffer is intended to be used
162174
/// in conjunction with a rendering buffer of type `Buffer<(UIContext, usize)>` during the merge process.
163175
///
164176
/// For optimal performance, it is recommended that this function runs concurrently with the rendering process.
165177
#[must_use]
166178
#[inline]
167-
pub async fn prepare(&mut self) -> Buffer<usize> {
179+
pub async fn prepare(&mut self) -> Prepared<UIContext> {
168180
info!("Preparing");
169181
debug!("state on prepare {:?}", self.state);
182+
183+
if self.cushion_to_ui.is_none() {
184+
panic!(
185+
"{}",
186+
eyre!(
187+
"Cushion to UIContext did not set. Did you set UI?(This error is probably not called because of the way Rust works!)"
188+
)
189+
);
190+
}
191+
170192
let mut batch_count = if self.batch_size == 0 {
171193
usize::MAX
172194
} else {
@@ -262,6 +284,8 @@ where
262284
}
263285
}
264286

287+
let ctuf = self.cushion_to_ui.as_ref().unwrap();
288+
265289
let mut v: Vec<_> = v
266290
.into_iter()
267291
.filter(|ci| {
@@ -275,11 +299,14 @@ where
275299
.any(|filter| filter.predicate(&self.state.items[*ci], &self.state.input))
276300
}
277301
})
302+
.map(|ci| (ctuf(&self.state.items[ci]), ci))
278303
.collect();
279304

280-
v.sort_by(self.create_sorter());
305+
let sorterf = self.create_sorter();
306+
307+
v.sort_by(|(_, lhs), (_, rhs)| sorterf(lhs, rhs));
281308

282-
v.into()
309+
Prepared::new(v.into())
283310
}
284311

285312
/// Merges UI context data into the rendering buffer.
@@ -299,18 +326,14 @@ where
299326
pub fn merge(
300327
&mut self,
301328
buf: &mut Buffer<(UIContext, usize)>,
302-
mut from: Buffer<usize>,
329+
from: Prepared<UIContext>,
303330
) -> Result<bool> {
304-
ensure!(
305-
self.cushion_to_ui.is_some(),
306-
"Cushion to UIContext did not set. Did you set UI?(This error is probably not called because of the way Rust works!)"
307-
);
308331
debug!("state on merge: {:?}", self.state);
309332

310333
// sorterは順番に適用していくのと、逆にしてstd::Ordering::Equalが出たら次のやつを参照するっていうのが同義っぽいきがする
311334
// どっちにするかだけど、std::Ordering::Equalが出たら戻るほうが(ここでは逆にしたりしない)計算量が少なそう
312335

313-
let v = from.as_mut();
336+
let v = from.into_inner().into_inner();
314337

315338
let sorterf = self.create_sorter();
316339

@@ -321,23 +344,21 @@ where
321344
let mut merged = Vec::with_capacity(dst_owned.len() + v.len());
322345

323346
let mut iter_dst = dst_owned.into_iter();
324-
let mut iter_src = v.iter();
347+
let mut iter_src = v.into_iter();
325348

326349
let mut next_dst = iter_dst.next();
327350
let mut next_src = iter_src.next();
328351

329-
while let (Some(a), Some(b)) = (next_dst.as_ref(), next_src.as_ref()) {
330-
if sorterf(&a.1, b) != std::cmp::Ordering::Greater {
331-
merged.push(next_dst.take().unwrap());
352+
while next_src.is_some() && next_src.is_some() {
353+
let (Some(a), Some(b)) = (next_dst.take(), next_src.take()) else {
354+
unreachable!()
355+
};
356+
357+
if sorterf(&a.1, &b.1) != std::cmp::Ordering::Greater {
358+
merged.push(a);
332359
next_dst = iter_dst.next();
333360
} else {
334-
merged.push({
335-
let ui_ctx = (self.cushion_to_ui.as_ref().unwrap())(
336-
&self.state.items[*next_src.unwrap()],
337-
);
338-
339-
(ui_ctx, *next_src.unwrap())
340-
});
361+
merged.push(b);
341362
next_src = iter_src.next();
342363
}
343364
}
@@ -347,16 +368,8 @@ where
347368
merged.extend(iter_dst);
348369
}
349370
if let Some(val) = next_src {
350-
merged.push({
351-
let ui_ctx = (self.cushion_to_ui.as_ref().unwrap())(&self.state.items[*val]);
352-
353-
(ui_ctx, *val)
354-
});
355-
merged.extend(iter_src.map(|ci| {
356-
let ui_ctx = (self.cushion_to_ui.as_ref().unwrap())(&self.state.items[*ci]);
357-
358-
(ui_ctx, *ci)
359-
}));
371+
merged.push(val);
372+
merged.extend(iter_src);
360373
}
361374

362375
*dst = merged;

src/ui.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ impl<T> Buffer<T> {
4141
*self = Self::default();
4242
}
4343

44+
#[inline]
45+
pub(crate) fn into_inner(self) -> Vec<T> {
46+
self.vec
47+
}
48+
4449
#[inline]
4550
pub(crate) fn as_mut(&mut self) -> &mut Vec<T> {
4651
&mut self.vec

0 commit comments

Comments
 (0)