Quickest summary: Rust async is >3x faster and lighter than Linux threads. This is a great accomplishment for Rust.
Comparison of Rust async and Linux thread context switch time and memory use
31–40 of 201 posts
Re: Comparison of Rust async and Linux thread context switch time and memory use
#32Quickest summary: Rust async is >3x faster and lighter than Linux threads. This is a great accomplishment for Rust.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#33I am not surprised that the cost of context switching due to I/O readiness can often be roughly equal between async tasks and kernel threads. Normal blocking I/O can be surprisingly efficient because of various factors, such as a reduced need for system calls. Think about it this way—if you have a user-space thread which wakes up due to I/O readiness, then this means that the relevant kernel thread woke up from epoll…
Then why is it that IO-heavy benchmarks such as the Techempower web benchmark are dominated by async frameworks? The fastest results there are all from async frameworks [1]. And among Rust frameworks the same pattern holds. The fastest Rust frameworks are async while a synchronous frmework such as Rocket is about 20x slower. [1] https://www.techempower.com/benchmarks/#section=data-r20&hw=... [2] https://www.techempow…
Re: Comparison of Rust async and Linux thread context switch time and memory use
#34I am not surprised that the cost of context switching due to I/O readiness can often be roughly equal between async tasks and kernel threads. Normal blocking I/O can be surprisingly efficient because of various factors, such as a reduced need for system calls. Think about it this way—if you have a user-space thread which wakes up due to I/O readiness, then this means that the relevant kernel thread woke up from epoll…
Re: Comparison of Rust async and Linux thread context switch time and memory use
#35I am not surprised that the cost of context switching due to I/O readiness can often be roughly equal between async tasks and kernel threads. Normal blocking I/O can be surprisingly efficient because of various factors, such as a reduced need for system calls. Think about it this way—if you have a user-space thread which wakes up due to I/O readiness, then this means that the relevant kernel thread woke up from epoll…
Then why is it that IO-heavy benchmarks such as the Techempower web benchmark are dominated by async frameworks? The fastest results there are all from async frameworks [1]. And among Rust frameworks the same pattern holds. The fastest Rust frameworks are async while a synchronous frmework such as Rocket is about 20x slower. [1] https://www.techempower.com/benchmarks/#section=data-r20&hw=... [2] https://www.techempow…
Re: Comparison of Rust async and Linux thread context switch time and memory use
#36I am not surprised that the cost of context switching due to I/O readiness can often be roughly equal between async tasks and kernel threads. Normal blocking I/O can be surprisingly efficient because of various factors, such as a reduced need for system calls. Think about it this way—if you have a user-space thread which wakes up due to I/O readiness, then this means that the relevant kernel thread woke up from epoll…
This benchmark as written is probably underestimating kernel task scheduling cost since only 1 task is runnable at any 1 time, while a realistic multi-threaded system will have more runnable threads to juggle.
0: http://pdxplumbers.osuosl.org/2013/ocw//system/presentations...
Re: Comparison of Rust async and Linux thread context switch time and memory use
#37So the Rust async context switch is on top of the regular Linux context switch, not instead.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#38Earlier quoted context omitted.
I read it as most people are over investing in async rust.
What makes you think that? Looking at the summary it looks like async is better in every way.
* Rust's async ecosystem [1] adds a lot of complexity over simple threaded code.
* Rust's async ecosystem doesn't interoperate as easily with C libraries written in a simple threaded way. (And it's debatable which interoperates more easily with C libraries written with a different event loop.)
* async tasks can't be preempted, so concurrency will fall off a cliff if they run on O(cpus) threads and involve long-running computations or accidental blocking.
I think it's reasonable to ask if these numbers are enough better to justify all that, particularly given the disappointing "this advantage goes away if the context switch is due to I/O readiness".
And to go back and argue pro-async for a moment, io_uring might eliminate that disappointing caveat.
Then again, on the pro-thread side, there's Google's interesting fibers model that might solve some of these performance issues. [2] Also, "~17µs for a new kernel thread" is the wrong number, since you can avoid that cost with a simple thread pool.
Personally I think some things are better written as async, but it's a mistake to impose it on everything. For example, if you're writing a web app in Rust, I think you're usually better off writing threaded request handlers and having a mechanism for them to interact with the async hyper code. The hyper code is better off as async because an Internet-facing server might have an enormous number of connections in keepalive state.
[1] or maybe I should say ecosystems, plural, given the current tokio vs async-std divide.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#39Earlier quoted context omitted.
io_uring will help a lot here.
Well, it can, but not always. Remember that if you’re waiting for an event to arrive, that generally involves a syscall, the thread being put to sleep, and then the thread being woken up. Any time you’re doing that, think, “Could I just replace this polling system with a call to read()?” What io_uring does do is provide a way to poll without needing to wait, but if you haven’t received new events when you poll, you’r…
Isn't "not on the fast path any more" a bit absolutist? io_uring's "slow" path is roughly one syscall per iteration, right? That's still many fewer syscalls than one syscall per IO operation (or more if any return EAGAIN/EWOULDBLOCK) as you'd be doing without it. I'm not sure I really care about eliminating that last syscall per iteration; it seems minor in comparison.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#40Please don't mix nanoseconds and microseconds. This is just confusing to read. Stick to nanoseconds for everything.