Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Rust implements polling-style async. In other words, futures need to be explicitly driven to perform work, and don't consume any resources beyond local state otherwise.
In the original code, the
tokio
andasync_std
examples create their respective runtimes' coroutines, taking little space (just the instant to be woken at, plus a bit of metadata), and these coroutines are then driven byfutures::future::join_all
.join_all
, in turn, is driven by the async runtime. As such, the async runtime is only aware of one task, whilejoin_all
performs the driving. It stores multiple linked lists, metadata for waking, and other heaps of information, whiletokio
/async_std
store what is effectively a priority queue of wakers.On the other hand, async runtimes provide ways to spawn "real" tasks, which are tracked and driven by the async runtime rather than
futures
. These tasks are more heavy-weight, but can run on their own threads (unlikefutures
, which has to use one thread) and can run in background without being driven by another future explicitly.In effect, the original code measures the performance of
join_all
more than the async runtimes, which is whytokio
andasync_std
got such similar benchmark results despite having very different internals. Therefore, this PR:Introduces a
rust_futures
benchmark, which testsfutures
by design rather than accidentally. It uses idiomaticjoin_all
code. It's based ontokio
coroutines rather thanasync_std
, but the influence of the runtime is negligible, as most of the memory utilization is byfutures
rather than the async runtime.Updates the
rust_async_std
andrust_tokio
benchmarks to spawn native async runtime tasks without cheating withfutures
.As a result,
tokio
andasync_std
fare worse than in the current benchmark results, butfutures
gets the best result due to not needing to collect the futures to an intermediate vector.Some more context is available in #1; also read the discussion there for why the appendix in the post is incorrect.