gpui2: Type-erase futures.

Project2's LLVM IR size is ~20-25% bigger than project1 due to the fact that in gpui2 we call async_task::spawn(_local) with impl Future instead of dyn Future, which leads to quite a few more instantiations of RawTask.

LLVM-IR size for project2:
|  build_type  |  main   |  this branch  | project1 |
|  debug       | 2617795 |    2022814    | 1817866  |
|  release     | 4439033 |    3715086    | 3314489  |
This commit is contained in:
Piotr Osiewicz 2023-11-08 12:54:37 +01:00
parent d67581875f
commit 2364f6b22e

View file

@ -68,7 +68,8 @@ impl<T> Future for Task<T> {
} }
} }
} }
type AnyLocalFuture<R> = Pin<Box<dyn 'static + Future<Output = R>>>;
type AnyFuture<R> = Pin<Box<dyn 'static + Send + Future<Output = R>>>;
impl BackgroundExecutor { impl BackgroundExecutor {
pub fn new(dispatcher: Arc<dyn PlatformDispatcher>) -> Self { pub fn new(dispatcher: Arc<dyn PlatformDispatcher>) -> Self {
Self { dispatcher } Self { dispatcher }
@ -81,10 +82,16 @@ impl BackgroundExecutor {
R: Send + 'static, R: Send + 'static,
{ {
let dispatcher = self.dispatcher.clone(); let dispatcher = self.dispatcher.clone();
let (runnable, task) = fn inner<R: Send + 'static>(
async_task::spawn(future, move |runnable| dispatcher.dispatch(runnable)); dispatcher: Arc<dyn PlatformDispatcher>,
runnable.schedule(); future: AnyFuture<R>,
Task::Spawned(task) ) -> Task<R> {
let (runnable, task) =
async_task::spawn(future, move |runnable| dispatcher.dispatch(runnable));
runnable.schedule();
Task::Spawned(task)
}
inner::<R>(dispatcher, Box::pin(future))
} }
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
@ -243,11 +250,17 @@ impl ForegroundExecutor {
R: 'static, R: 'static,
{ {
let dispatcher = self.dispatcher.clone(); let dispatcher = self.dispatcher.clone();
let (runnable, task) = async_task::spawn_local(future, move |runnable| { fn inner<R: 'static>(
dispatcher.dispatch_on_main_thread(runnable) dispatcher: Arc<dyn PlatformDispatcher>,
}); future: AnyLocalFuture<R>,
runnable.schedule(); ) -> Task<R> {
Task::Spawned(task) let (runnable, task) = async_task::spawn_local(future, move |runnable| {
dispatcher.dispatch_on_main_thread(runnable)
});
runnable.schedule();
Task::Spawned(task)
}
inner::<R>(dispatcher, Box::pin(future))
} }
} }