-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-heavyIssue: Problems and improvements with respect to binary size of generated code.Issue: Problems and improvements with respect to binary size of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Maybe a duplicate of #52924, but maybe also something else.
I observed that the sizes of Future
s generated by async fns can grow exponentially.
The following code shows an async fn, which produces a 1kB future. Each layering in another async fn doubles it's size:
#![feature(async_await)]
async fn i_am_1kb() -> bool
{
let x: [u8; 1*1024] = [0; 1*1024];
async{}.await;
let _sum: u8 = x.iter().sum();
true
}
fn main() {
let fut1 = i_am_1kb();
dbg!(std::mem::size_of_val(&fut1));
let composed_1 = async {
let inner = i_am_1kb();
inner.await;
};
dbg!(std::mem::size_of_val(&composed_1));
let composed_2 = async {
let inner = i_am_1kb();
dbg!(std::mem::size_of_val(&inner));
inner.await;
};
dbg!(std::mem::size_of_val(&composed_2));
let composed_3 = async {
let inner = async {
let inner = async {
i_am_1kb().await;
};
dbg!(std::mem::size_of_val(&inner));
inner.await;
};
dbg!(std::mem::size_of_val(&inner));
inner.await;
};
dbg!(std::mem::size_of_val(&composed_3));
}
Output:
[src/main.rs:16] std::mem::size_of_val(&fut1) = 1032
[src/main.rs:22] std::mem::size_of_val(&composed_1) = 1036
[src/main.rs:29] std::mem::size_of_val(&composed_2) = 2072
[src/main.rs:44] std::mem::size_of_val(&composed_3) = 4168
It doesn't matter whether the statement between the future generation and await!
references the future or not. A simply println("")
will have the same effect.
Only if the future is directly awaited (as in composed_1
) the size will stay constant.
cc @cramertj , @nikomatsakis , @Nemo157
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-heavyIssue: Problems and improvements with respect to binary size of generated code.Issue: Problems and improvements with respect to binary size of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.