-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example of custom async task with single block_on #2650
Conversation
bfeb722
to
d2cc62b
Compare
d2cc62b
to
d847244
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be more of a benchmark than an example. Can it be moved to benches
?
@NiklasEi Thanks! Sure I can add another micro-benchmark to the benches, in the meanwhile, this one is more like a small toy program that exercises the main stacks of bevy ecs, and show numbers in an E2E scenario. I think micro-benchmark and small benchmark program serves different purposes and should co-exsist. BTW, It does show a huge perf gap between using single and multiple block_on(s), regarding my question below, where is the best place for discussion? GH discussion or discord?
|
The difference between On the difference between multiple
Are you suggesting something like struct TaskResult<T>(T);
pub fn handle_tasks<T: Component>(
mut commands: Commands,
mut tasks: Query<(Entity, &mut Task<T>)>,
) {
let done = tasks.iter_mut().map(|(entity, mut task)| async move {
if let Some(r) = poll_once(&mut *task).await {
Some((entity, r))
} else {
None
}
});
block_on(async {
for f in done {
if let Some((entity, result)) = f.await {
commands
.entity(entity)
.remove::<Task<T>>()
.insert(TaskResult(result));
}
}
});
} It's possible to add in Bevy, but as it needs to be generic over the task type, you would still need some kind of registration mechanic for your tasks |
@mockersf Thanks! I'm thinking of sth like this, users still register Task but can query pub fn handle_tasks<T: Component>(
mut commands: Commands,
mut tasks: Query<(Entity, PollOnce<Task<T>>)>,
) {
block_on(async {
for entity, task in tasks{
if let Some(result) = task.await {
commands
.entity(entity)
.remove::<Task<T>>()
.insert(TaskResult(result));
}
}
});
} Or, if async fn can be used, ecs will do the block_on part pub async fn handle_tasks<T: Component>(
mut commands: Commands,
mut tasks: Query<(Entity, &mut Task<T>)>,
) {
for (entity, mut task) in transform_tasks.iter_mut() {
n_tasks += 1;
let ret = poll_once(&mut *task).await;
if ret.is_some() {
commands.entity(entity).remove::<Task<bool>>();
}
}
} |
This PR adds a new example. Adding module and item level doc comments, as described in:
would be really useful to those who will browse examples. I think it's sufficient to move the description on the top, as a module level doc comment. I also think this should not be advertized as a benchmark, as examples are built without optimizations by default. |
Adding the Adopt-Me tag; I think this is valuable but the issues never got fixed. |
Objective
poll_once
andblock_on
in user code, it gets the best performance.Solution
cargo run --release --example async_bench