Asynchronous Programming in Rust
blog.yoshuawuyts.com
blog.yoshuawuyts.com
Having gone through this pain last weekend, I’m a bit wary of examples that are roughly stateless (or at least only do copying between channels). To all rust folks making samples: if you can mix in even a bit of mutable shared state (like a counter, logging, etc.), it goes a long way to showing whether your system can handle scoped threads/tasks, shared state, and straightforward concurrency ergonomically.
If you compare and contrast the docs for crossbeam’s scoped threads, Rayon’s scope, and an attempt at DIY via raw thread::spawn, I think you want to see the same clarity on the future/async/await side. Richer examples can really elucidate the pros and cons of different paths.
Maybe some people are in to that for fun, but the for the majority of people, the message should be:
stick with stable folks.
Out of all things regarding async programming in Rust, runtime seems like one of the less important aspects. Stabilization, ecosystem, syntax, and even no_std support seem far more important.
Hello? Cloud computing (i.e. datacenter software) requires zillions of concurrent "fibers" on a much smaller number of OS threads.
In this case, it’s taken a lot of time (not by me, but other extremely devoted and thoughtful people) to experiment with interfaces and create things like Pin that actually allow for async/await to work with shared references between state-machines.
This is a complex topic, and being an early adopter of async in Rust, I’m very happy that the wrong thing didn’t land early, but instead we’re getting a very well thought out system.
As a guy who actually wrote "datacenter software" for over a decade: you don't speak from experience and what you said is false.
Basically, OS threads are the smallest and lightest form of concurrency currently in existence. Any userspace 'fiber' will be heavier and slower than actually spawning a pthread.
The problem is when you couple pthreads with interpreter runtimes. (Python, Lua, Ruby, etc.) These runtimes (and especially the GC engines they use!) don't play nice with OS threads, so you're forced to invent various rube-goldberg fiber-like contraptions on async primities.
The end result is slower, heavier and more brittle than any pthread-only solution, but interpreter runtimes necessarily impose overhead, you learn to deal with it.
Either is far lighter weight than an OS thread.
What userspace fibers are you referring to?
I don't have experience with Python, Ruby, or Lua, but IIRC Python has an async mode not unlike Node.js.
If you don't have to provide POSIX thread semantics, then a user space thread can be much smaller than a OS thread; for example, an Erlang process can be as small as 1.2 KB [1], and a thread in GHC's runtime can be even smaller than that [2, section 4].
With both of these, the programmer writes synchronous code that blocks on IO, and the runtime is responsible for turning that into async IO operations at the OS level.
[1] http://erlang.org/doc/efficiency_guide/processes.html
[2] https://www.microsoft.com/en-us/research/wp-content/uploads/...
Context switching between fibers can be extraordinarily fast because the kernel is not involved. I have some experience in the matter.