Skip to content

Commit 4d50a9c

Browse files
committed
rework executor code for performance
1 parent 7ca4341 commit 4d50a9c

File tree

1 file changed

+19
-32
lines changed

1 file changed

+19
-32
lines changed

crates/bevy_tasks/src/task_pool.rs

+19-32
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use std::{
22
future::Future,
33
marker::PhantomData,
44
mem,
5-
pin::Pin,
65
sync::Arc,
76
thread::{self, JoinHandle},
87
};
98

109
use concurrent_queue::ConcurrentQueue;
11-
use futures_lite::{future, pin};
10+
use futures_lite::{future, FutureExt};
1211

1312
use crate::Task;
1413

@@ -235,40 +234,28 @@ impl TaskPool {
235234

236235
f(scope_ref);
237236

238-
let fut = async move {
239-
let mut results = Vec::with_capacity(spawned.len());
240-
while let Ok(task) = spawned.pop() {
241-
results.push(task.await);
242-
}
237+
future::block_on(async move {
238+
let fut = async move {
239+
let mut results = Vec::with_capacity(spawned.len());
240+
while let Ok(task) = spawned.pop() {
241+
results.push(task.await);
242+
}
243243

244-
results
245-
};
244+
results
245+
};
246246

247-
// Pin the futures on the stack.
248-
pin!(fut);
249-
250-
// SAFETY: This function blocks until all futures complete, so we do not read/write
251-
// the data from futures outside of the 'scope lifetime. However,
252-
// rust has no way of knowing this so we must convert to 'static
253-
// here to appease the compiler as it is unable to validate safety.
254-
let fut: Pin<&mut (dyn Future<Output = Vec<T>> + 'static + Send)> = fut;
255-
let fut: Pin<&'static mut (dyn Future<Output = Vec<T>> + 'static + Send)> =
256-
unsafe { mem::transmute(fut) };
257-
258-
// The thread that calls scope() will participate in driving tasks in the pool
259-
// forward until the tasks that are spawned by this scope() call
260-
// complete. (If the caller of scope() happens to be a thread in
261-
// this thread pool, and we only have one thread in the pool, then
262-
// simply calling future::block_on(spawned) would deadlock.)
263-
let mut spawned = task_scope_executor.spawn(fut);
264-
loop {
265-
if let Some(result) = future::block_on(future::poll_once(&mut spawned)) {
266-
break result;
247+
let tick_forever = async move {
248+
loop {
249+
// only yield every 200 ticks
250+
self.executor.try_tick();
251+
task_scope_executor.try_tick();
252+
253+
future::yield_now().await
254+
}
267255
};
268256

269-
self.executor.try_tick();
270-
task_scope_executor.try_tick();
271-
}
257+
fut.or(tick_forever).await
258+
})
272259
}
273260

274261
/// Spawns a static future onto the thread pool. The returned Task is a future. It can also be

0 commit comments

Comments
 (0)