The author admits that they needed Arc/clone in a footnote. So I think the more interesting title would be to rehash/interpret this as “Why asynchronous Rust is too hard”.
Having played with this a bit recently, I think folks are going to end up:
- assuming Tokio (now that it’s 1.xx)
- mark nearly everything as async
- push callers to use rt.block_on to wait for an async function from non-async code
I definitely miss the easy concurrency of golang the author refers to (more so in the colored functions post), particularly since AFAICT, tokio is basically going to become the default assumption. So Rust is technically pluggable here, but won’t be in practice. Does that mean that embedded folks end up having their own !tokio that they prefer? Maybe! But they’ll get locked out of the “assume tokio” ecosystem.
I noticed this a few months ago as well. I was looking for a way to do simple synchronous HTTPS requests in a CLI, and it seemed like using `reqwest` with tokio was more or less the default option in Rust. I ended up using ureq, and it looked like there may have even been ways to avoid it using hyper and an alternative tls-connector but the simplest solution seemed to be "just use tokio".
When something foundational, like networking, gains a defacto dependency on tokio, it seems inevitable that a large footprint of the ecosystem will eventually depend on it.
Yeah, I started with reqwest because it was easy, then wanted more control (reqwest has a hardcoded 8? KiB buffer!) and went to hyper directly, and then realized I should replace all reqwest usage with just async usage of hyper.
Doing so then colored/infected everything with async. It wasn’t actually bad in the end, but if you’re just trudging along trying to do your job, you suddenly walk into a “and now update all of this”. Staring at the innards of reqwest::blocking though made me realize “if I care about performance at all, I really shouldn’t use this”. One of my main reasons was so that I’d know there was only my inclusion of tokio/the version I wanted (reqwest lagged a bit, so then I had hyper w/ tokio1.0 and reqwest with an older hyper with an older tokio... and I was worried about understanding that interaction).
> AFAICT, tokio is basically going to become the default assumption
I've noticed this as well. And then there are the libs that don't support async, like diesel. I lost time trying to find the right combination of libraries for a web project. There are a lot of things I don't like about Go, but this part is easier.
Having played with this a bit recently, I think folks are going to end up:
- assuming Tokio (now that it’s 1.xx)
- mark nearly everything as async
- push callers to use rt.block_on to wait for an async function from non-async code
I definitely miss the easy concurrency of golang the author refers to (more so in the colored functions post), particularly since AFAICT, tokio is basically going to become the default assumption. So Rust is technically pluggable here, but won’t be in practice. Does that mean that embedded folks end up having their own !tokio that they prefer? Maybe! But they’ll get locked out of the “assume tokio” ecosystem.