Skip to content

Rewrite Rust benchmarks #5

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

Merged
merged 1 commit into from
Dec 1, 2024
Merged

Conversation

purplesyringa
Copy link

@purplesyringa purplesyringa commented Nov 30, 2024

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 and async_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 by futures::future::join_all. join_all, in turn, is driven by the async runtime. As such, the async runtime is only aware of one task, while join_all performs the driving. It stores multiple linked lists, metadata for waking, and other heaps of information, while tokio/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 (unlike futures, 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 why tokio and async_std got such similar benchmark results despite having very different internals. Therefore, this PR:

  • Introduces a rust_futures benchmark, which tests futures by design rather than accidentally. It uses idiomatic join_all code. It's based on tokio coroutines rather than async_std, but the influence of the runtime is negligible, as most of the memory utilization is by futures rather than the async runtime.

  • Updates the rust_async_std and rust_tokio benchmarks to spawn native async runtime tasks without cheating with futures.

As a result, tokio and async_std fare worse than in the current benchmark results, but futures 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.

@hez2010 hez2010 merged commit 515de86 into hez2010:main Dec 1, 2024
1 check passed
@hez2010
Copy link
Owner

hez2010 commented Dec 1, 2024

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants