this post was submitted on 13 Jun 2023
23 points (100.0% liked)

Rust Lang

148 readers
1 users here now

Rules [Developing]

Observe our code of conduct

Constructive criticism only

No endless relitigation

No low-effort content

No memes or image macros

No NSFW Content

founded 1 year ago
MODERATORS
 

In the interest of sparking a little discussion (not too spicy please, we're having a nice clean start here) I thought I would ask the question. It's something I'm legitimately wondering about as someone who has reached for tokio by default for years.

I'm aware of async-std and smol, probably unaware of others. If you've used or prefer a different async runtime, what trade-offs might I be interested in or what features am I missing out on?

all 5 comments
sorted by: hot top controversial new old
[–] [email protected] 13 points 1 year ago (1 children)

There are executors for more specific use cases.

  • For example, bastion is a "Highly-available Distributed Fault-tolerant Runtime", inspired by Erlang, and including an async executor.
  • embassy includes an async executor specifically for embedded systems.
  • fuchsia-async is an executor for use in the Fuchsia OS.
  • wasm-bindgen-futures converts Rust Futures to JavaScript Promises and schedules them to run to completion. It could also be seen as a (very basic) executor.
[–] [email protected] 6 points 1 year ago

I think gtk-rs is another interesting example. The glib crate provides an async executor, since glib already requires running its main loop. So if you just need to run a couple futures you don't need another executor in one or more other threads, and tasks spawned in the glib executor can call functions that need to be run in that thread, since gtk types are generally not thread safe.

So integrating into other things could be a reason to use a different executor..

[–] [email protected] 6 points 1 year ago (1 children)

Not so much relevant for production use cases but from an educational point of view: whorl is pretty great. One file that explains async runtime basics from top to bottom. The cleverness of doing this in one source code file is remarkable.

[–] [email protected] 4 points 1 year ago

This won't really help you consider another runtime specifically, but it is an instance of not choosing Tokio.

When I was benchmarking with Tokio I found it had quite a difference (higher cpu usage) to other options I was exploring. My specific use-case was an async single-threaded application which does mostly network io + timers. I would be interested to see how Tokio fairs today (I tested it over a year ago) and quite possibly any advice or tips in writing efficient code with it. My benchmark was send/recv with a UDP socket and print out stats in a timer (that's the core idea of what I needed to use it with). Comparing both CPU usage and maximum throughput.

For normal async, I would probably still reach for Tokio, but the use case I was looking at was very much specific to what I was working on at my job (still am), and lower CPU usage as well as higher throughput is what we needed. We ended up building a small internal runtime that uses mio, it was also fun to implement. In the benchmarks we ran, it used less CPU % than Tokio, and achieved higher throughput, by enough that we thought it was worth continuing to use our internal one.