Earlier quoted context omitted.
> Perhaps surprisingly, the future within a task compiles down to a state machine, so that every time the task wakes up to continue polling, it continues execution from the current state How are those tasks implemented, and what's scheduling them?
You need a third-party library to provide an executor. Rust does not come with one to keep the runtime size small. The community seems to have centralized on https://tokio.rs/ (under the hood it uses epoll/whatever OS-specific functionality to schedule M:N) See: https://news.ycombinator.com/item?id=20722297
How Rust optimizes async/await
21–30 of 130 posts
Re: How Rust optimizes async/await
#22Earlier quoted context omitted.
epoll io loop performs better for most network io though and is simplier to manage when you have to start dealing with out of band issues (like efficient hearbeats - every time I've had a conversation without how to move some of the heartbeat code over to async it comes down to just accepting it isn't going to be as efficient as my c++ implementation and either strain heavily of accept over publication). Last time I…
Honestly I don’t get it why simply using mio (epoll, kqueue, iocp wrapper) is so unpopular.
Re: How Rust optimizes async/await
#23As a reminder, you don't need to use async/await to implement socket servers in Rust. You can use threads, and they scale quite well. M:N scheduling was found to be slower than 1:1 scheduling on Linux, which is why Rust doesn't use that solution. Async/await is a great feature for those who require performance beyond what threads (backed by either 1:1 or M:N implementations) can provide. One of the major reasons behi…
Re: How Rust optimizes async/await
#24Re: How Rust optimizes async/await
#25Earlier quoted context omitted.
You need a third-party library to provide an executor. Rust does not come with one to keep the runtime size small. The community seems to have centralized on https://tokio.rs/ (under the hood it uses epoll/whatever OS-specific functionality to schedule M:N) See: https://news.ycombinator.com/item?id=20722297
How's that play out in terms of, say, performing some long-running calculations, rather than something that performs IO?
It's also possible to write a long-running computation as a future, which can yield after some smaller amount of work to let some IO get done. But I'm not sure if that's the recommended approach.
Re: How Rust optimizes async/await
#26Earlier quoted context omitted.
Honestly I don’t get it why simply using mio (epoll, kqueue, iocp wrapper) is so unpopular.
See these examples of how async/await simplifies looping and error handling: https://docs.rs/dtolnay/0.0.3/dtolnay/macro._01__await_a_min... . Await syntax makes it much easier to compose asynchronous code from different libraries, in the same way that ordinary function calls compose synchronous code. Talking to epoll/mio directly is certainly possible, but it's hard to make two different libraries work well together…
Re: How Rust optimizes async/await
#27Earlier quoted context omitted.
You need a third-party library to provide an executor. Rust does not come with one to keep the runtime size small. The community seems to have centralized on https://tokio.rs/ (under the hood it uses epoll/whatever OS-specific functionality to schedule M:N) See: https://news.ycombinator.com/item?id=20722297
How's that play out in terms of, say, performing some long-running calculations, rather than something that performs IO?
Cooperative scheduling is used to schedule tasks on executors. A single executor is expected to manage many tasks across a small set of threads. There will be a far greater number of tasks than threads. There also is no pre-emption. This means that when a task is scheduled to execute, it blocks the current thread until the poll function returns.
Because of this, it is important for implementations of poll to only execute for very short periods of time. For I/O bound applications, this usually happens automatically. However, if a task must run a longer computation, it should defer work to a blocking pool [1] or break up the computation into smaller chunks and yield back to the executor after each chunk. [2]
"poll" here refers to the callback function in the future that actually does the work.
[1] https://docs.rs/tokio-threadpool/0.1.15/tokio_threadpool/fn....
Re: How Rust optimizes async/await
#28Re: How Rust optimizes async/await
#29Re: How Rust optimizes async/await
#30As a newcomer to Rust, wishing that this post was one of the first ones I've read about this topic. It took scouring through many many posts, some of them here on HN, to be able to grasp some of the same idea. (I may not be alone, judging from the very long discussion the other day: https://news.ycombinator.com/item?id=20719095 )