Open chaoticgood1 opened 3 years ago
You are trying to use a tokio future (as returned by tokio::time::delay_for
) with the async-executor
runtime used by bevy. This isn't allowed. A tokio future can only be awaited within a tokio runtime, as the tokio future needs to tell the tokio runtime when to wake up again. The async-executor
runtime doesn't have any timer functionality builtin and especially not a tokio flavor timer functionality.
Our tasks infrastructure is not tokio based. Imo, it is a tokio bug that this future is not generically callable, however I also don't think tokio could have a better strategy - this area likely needs more work.
The easiest way to do this is to try using async_std::task::sleep
, which might work for you. Otherwise you'll have to create your own tokio threadpool, i.e. a version of bevy_tasks
based on tokio
. A quick search suggest that https://crates.io/crates/bevy_spicy_networking might be tokio based too, so investigating that would be useful
The title is misleading; I think a more accurate title would be something like "Cannot use tokio tasks within a TaskPool
".
(and we could probably move this to a discussion too, would be titled 'How to use tokio tasks with bevy?')
Oh, sorry for the vague sample, I am required to call await inside the async because we need to use sqlx to query database.
Something like this. I just use the delay_for() to simulate the work done and use await, as we detected it to be the cause of the problem.
let task = thread_pool.spawn(async move {
let query = sqlx::query_as!(Data,
"query here" )
.fetch_all(&db)
.await;
// Process result
Result
});
commands.spawn().insert(task);
The issue is not the await
, it's the async runtime used by sqlx. It seems it supports multiple runtime, which are you using?
https://github.com/launchbadge/sqlx/blob/f0d0dce8e25c40dffd1431776b6a38510a70bde0/Cargo.toml#L71-L73
We are using tokio 0.2.22 and sqlx 0.4.2.
As said above, Tokyo won't easily work with Bevy.
You could try with runtime async-std, it should be better supported (though I didn't try myself)
It will be great to be able to change the async execution engine, it's actually possible to achieve this with very minimal changes by using async-global-executor, which is built on top of async-executor and has the capability to switch to async-io / tokio backend. I tried locally both async-io and tokio works fine with the examples, and tokio works fine with the code above, I can put up a PR for review.
BTW, I did some performance tests before (not related to bevy tho) and found different async execution engines do have non-trivial performance gaps in dealing with massive tasks, like 20%~30% in my test scenario. (It showed tokio is much more performant)
For anyone looking to run tokio
executor compatible async code (including tokio
functions like tokio::time::sleep
), you can do so using the async-compat
crate:
For anyone looking to run
tokio
executor compatible async code (includingtokio
functions liketokio::time::sleep
), you can do so using theasync-compat
crate:
are there any performance implications for using this with multiple requests?
the future will enter the context of a global single-threaded tokio runtime started by this crate
So I think this means all futures that are passed through the compat are run on a single thread. Granted this is probably performant enough for me, just curious on anyone else's considerations
Bevy version
0.5
Operating system & version
Ubuntu 20.04
What you did
Run the code
What you expected to happen
Should run with no panic
What actually happened
Panics and shows this error
Bug confirmed with @ashneverdawn