Remix.run Logo
fl0ki 8 hours ago

Async ruined Rust for me, even though I write exactly the kind of highly concurrent servers to which it's supposed to be perfectly suited. It degrades API surfaces to the worst case :Send+Sync+'static because APIs have to be prepared to run on multithreaded executors, and this infects your other Rust types and APIs because each of these async edges is effectively a black hole for the borrow checker.

Don't get me started on how you need to move "blocking" work to separate thread pools, including any work that has the potential to take some CPU time, not even necessarily IO. I get it, but it's another significant papercut, and your tail latency can be destroyed if you missed even one CPU-bound algorithm.

These may have been the right choices for Rust specifically, but they impair quality of life way too much in the course of normal work. A few years ago, I had hope this would all trend down, but instead it seems to have asymptoted to a miserable plateau.

the__alchemist 4 hours ago | parent | next [-]

Its interesting how there are so many ways to do various types of concurrency in rust (Hardware-dependent) that don't introduce coloring:

  - Hardware interrupts
  - Threads
  - Thread pools / Rayon
  - GPU (Cudarc, FFI, WGPU etc)
  - SIMD
  - Write firmware for multiple cores
I make use of all of those, but still prefer avoiding Async, for the typical coloring reason. I can integrate the above things into a code base with low friction; Async poses a compatibility barrier.
cmrdporcupine 2 hours ago | parent | prev | next [-]

I do Rust without async and I'm happier for it.

But yes, once you go dining on other people's crates you definitely get the impression that you have to, because tokio gets its fingerprints all over everything.

But also there are non-thread stealing runtimes that don't require Send/Sync on the Future. Just nobody uses them.

Because Rust is the language that tokio ate.

bluegatty 8 hours ago | parent | prev | next [-]

Is there hope that green threads could solve this?

convolvatron 7 hours ago | parent | prev | next [-]

this is dead true to me. I write systems code. Rust is supposed to be a systems language. Because I do work that is effectively always written as if it's in the kernel mode and distributed over the network, everything I do is async by default. And the ergonomics around async are just miserable, littered with half-finished implementations and definitions (i.e. async streams, async traits), and a motley bunch of libraries that are written to use particular modes of tokio that don't necessary play well together. its a giant bodge that would be excusable if that wasn't supposed to be part of the core applicability of the language. not to mention that the whole borrower business becomes largely useless, so you forgot to add Arc+Mutex, and Pin implicitly to your list of wrapper type signatures.

what bother me the most, is that aside from async, I _really_ do like the language and appreciate what its trying to do. otherwise I would just turn away from the whole mess. this just landed really badly.

josephg 5 hours ago | parent [-]

I completely agree. I really like rust, but all the async stuff is so half baked. It’s shocking coming from the JavaScript ecosystem. Async feels - comparatively - incredibly simple in JS. Even async streams are simple in JS and they work great. And I don’t have to wait 10 years for the linker to process all of tokio for a 1 line change.

Ygg2 7 hours ago | parent | prev [-]

> It degrades API surfaces to the worst case :Send+Sync+'static because APIs have to be prepared to run on multithreaded executors

This isn't true at all. The Send+Sync+'static is basically the limitation of tokio::spawn

https://emschwartz.me/async-rust-can-be-a-pleasure-to-work-w...

Change the executor, and the bound changes.

iknowstuff 5 hours ago | parent [-]

I think they mean tokio::spawn’s signature forces libraries that want to be easy to use with it to expose send+sync APIs (and thus use Arc+Mutex internally)