I kinda understand the difference between sync/async programming, threading vs. non-blocking I/O, etc. But I don't really understand the current trend of providing a synchronous interface ([cg]oroutines, async/await) on top of an asynchronous system. If you want synchronous code, why not use actual threads? In particular, what is the appeal of #Rust's #tokio from a programming perspective? I realize that threads may have a bit higher overhead, but is that the *only* reason to use tokio?
@ayo Yes, the thread overhead is pretty much the reason. Futures also compose nicely, so they replace several other synchronization primitives you'd use with threads.
@kornel Thanks. I'm rather surprised how much effort is spent on tokio, then - it's pretty invasive and affects almost every crate that may potentially do I/O.
Do you have any reading material on the ergonomics of futures vs. thread synchronisation? I'm familiar with the theory of Futures, but I've not used them much yet.
@ayo I don't have good reading materials on this :/
The invasive return types are almost on purpose: you know ahead of time that a function may need to wait for I/O. With bare threads you need extra knowledge to separate I/O-bound function calls from CPU-bound thread pools.
In Rust currently ergonomics of Futures are poor (hard for novices, mildly annoying if you're experienced). The point of async/await is to make it as convenient as blocking code, but with efficiency of async state machines.
@ayo If you want to handle many of simultaneous network connections then this overhead really matters. How many threads can you run in parallel? A few thousands maybe? Even if they are idle. Using async I/O I guess you should be able to handle 100thousands up to millions of connections.
Sounds nice but unfortunately I never got warm with Futures in Rust.
@t0k Oh I'm well aware of the performance differences, but how many applications have enough connections for it to matter? (I mean, threads scale perfectly well to 10k and don't even need that much more memory)
The effort and popularity of tokio gave me the impression that there were other reasons to prefer it over threads.
@ayo There is also some overhead when switching between threads (dumping all registers to memory and loading new ones). I would guess that this is less intensive for Futures. Just speculating...
@t0k I'm very good at speculating, myself. But without benchmarks it doesn't mean much. :P
(Speculating in the opposite direction: Non-blocking heavy I/O involves more syscalls, one syscall for polling, another for doing the I/O. With threads you just need one syscall to do the I/O. But like I said, it is very unlikely to matter for most applications)
Welcome to your niu world ! We are a cute and loving international community Ｏ(≧▽≦)Ｏ !