5 ms·
I don't understand, actix-web uses async / await and is ultra fast. https://www.techempower.com/benchmarks/ https://www.techempower.com/benchmarks/ Does this h
by claudiojulio 6y ago
I don't understand, actix-web uses async / await and is ultra fast. https://www.techempower.com/benchmarks/ https://www.techempower.com/benchmarks/
Does this have to do with the Tokio runtime that more efficiently coordinates the asynchronous code?
Automatically translated.
- digikata 6y agoI think the area is a lot more complex than the relative latency and throughput of synchronous vs async. For the observations in the environments of Ruby and Python, I think the observations feel true, but switching out to different sections of processing to different technologies I suspect different generalizations would have to be made.
- ramchip 6y agoI would take this benchmark with a huge grain of salt: https://64.github.io/actix/#blazingly-fast-or-not https://64.github.io/actix/#blazingly-fast-or-not
- breatheoften 6y agoI'd expect any python codebase which tries to use async/await based co-operative multi-tasking for concurrency at a larger scale would inevitably run into long-tail latency walls -- not just once but repeatedly as the codebase grows/changes. The potential for a code change or addition to produce unexpected synchronous blocking (potentially with GIL held) _somewhere_ seems really high and I have to imagine it would be very hard to avoid in the context of a real application codebase ...
- zelly 6y agoYou would have the same problem in Rust/Tokio and many other languages. The compiler is not able to know which calls could block. Suppose you have this async state machine server on a single thread, super fast, but somewhere it opens a file synchronously, let's say on a network mount to make things worse. No way a purely static VM-free language can help against that. Go (see: goroutines) is able to automatically suspend at those points and continue execution elsewhere. It comes with a big runtime but you get what you pay for.
- heftig 6y agoWhat's Go going to do if some ffi library written in C does a synchronous syscall? It's in the same situation.
- zelly 6y agoGo discourages C FFI but it runs those in kernel threads just to be safe. If you are using a lot of C FFI calls that all block, then it could be a problem (all cores are blocked).
- _-___________-_ 6y agoYes, but there’s nothing akin to the GIL in Rust/Tokio, so the potential impact of blocking is lower, and you can use spawn_blocking to move any blocking code (that you cannot eliminate) off the main worker threads that are polling futures, or use other techniques like run the blocking work on another standard thread and await on a channel for the result.
- billllll 6y agoSomeone please correct me if I'm wrong, but Rust async/await isn't implemented with green threads, but with OS threads. Those can be pre-empted.
- steveklabnik 6y agoAsync/await does not use threads of any kind. It creates a state machine. Executors may execute those state machines on a single thread, or map them to many threads. The latter looks kinda like green threads depending on what your definition of “green thread” is.
- gameswithgo 6y agonothing about how it works is built into the language, its up to user code/libraries to decide how to do it. the popular libraries like tokio are using something akin to green threads, though people picky about definitions may not agree to that nomenclature.
- sudeepj 6y ago> nothing about how it works is built into the language I think the state machine required to yield, async & await is baked into the language. But yes, one can implement the Future trait to take finer control.
- zelly 6y agoIt's single threaded and completely userspace. Rust async/await is a fancy way to write poll/epoll. It can limit the amount of time your program is blocked on IO (insofar as the implementation is as you would expect it (not guaranteed by the language)), but it will not do parallelism. For example you wouldn't async/await a prime number calculation--you'd have to use OS threads.
- comex 6y agoIt’s not necessarily single threaded; Rust async runtimes typically schedule tasks on a pool of multiple OS threads, usually one thread per CPU core. In other words, it can be seen as a form of M:N threading. Regarding the parent’s question, tasks cannot be preempted from their threads. Threads can of course be preempted from their CPU cores by the OS, but if the number of threads equals the number of cores, this will only happen if other processes on the system are competing for CPU time.