Live data from Hacker News

Comparison of Rust async and Linux thread context switch time and memory use

github.com

11–20 of 201 posts

Re: Comparison of Rust async and Linux thread context switch time and memory use

#12
post #9
post #7

I 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…

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’re not on the fast path any more. Whether you are often on the fast path for io_uring will depend on the particulars of your application and its I/O patterns.

Re: Comparison of Rust async and Linux thread context switch time and memory use

#13

> A context switch takes around 0.2µs between async tasks, versus 1.7µs between kernel threads. But this advantage goes away if the context switch is due to I/O readiness: both converge to 1.7µs. This is a big surprise. If you look at the Techempower web benchmark [1], the performance of actix-web is about 20x higher than that of Rocket. The common explanation is that actix-web is async and hence much faster than Roc…

Rocket's low performance could well be because the threadpool and DB connection pool is undersized: https://github.com/TechEmpower/FrameworkBenchmarks/blob/b891...

Re: Comparison of Rust async and Linux thread context switch time and memory use

#15
post #6
post #4

Quickest summary: Rust async is >3x faster and lighter than Linux threads. This is a great accomplishment for Rust.

It sound to me like comparing apples and oranges though. Parallelism (threads) and concurrency (aysnc in Rust) are not the same thing and can be actually used in combination.

You can happily use pthreads for concurrency up to ~10k before reaching for async.

Re: Comparison of Rust async and Linux thread context switch time and memory use

#16
post #7

I 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…

Linux is likely many years from having anything approaching a fully asynchronous system call interface, if anyone was willing to work on it (io_uring makes a huge dent but I don't think it's intending to reimplement everything). Even where async kernel interfaces exist, without reworking of the kernel-internal implementation still there is often the need for a thread for the kernel side to execute on. For example IIRC this is true for swathes of the vfs implementation at present.

So the whole thing is a bit of a false equivalence. Better interfaces that reduce context switches are desirable, but even where they exist often you are just substituting a user thread for a kernel one, and in the general case, there is likely to always be system interfaces that never make it into the brave new world -- take SysV IPC for example (a 1975 era API), it seems doubtful anyone would put the effort into making it async, but there will probably still be times where you might want to consume those interfaces for compatibility or some other obscure reason.

Also consider the case where a user program has a need for some substantial thread pools of its own, it might be the case in some scenarios that reusing resources that must already exist in user space and live in warmed caches makes more sense. Neither async or Linux threads are "better", it will always depend on a particular use case, and even then the right answer might well be some combination of both.

Re: Comparison of Rust async and Linux thread context switch time and memory use

#17
post #7

I 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.techempower.com/benchmarks/#section=data-r20&hw=...

Re: Comparison of Rust async and Linux thread context switch time and memory use

#18
post #4

Quickest summary: Rust async is >3x faster and lighter than Linux threads. This is a great accomplishment for Rust.

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.
Post reply on HN