Earlier quoted context omitted.
The way you have quoted this suggests it is being said by the author, whom you are disagreeing with. It's not: it's being said by someone else (in an issue filed against the repo), and the author also mostly disagrees.
Indeed. I read it as something written by the author. Double-checking revealed it was written by spacejam that did post the same argumentation over and over here on HN.
Comparison of Rust async and Linux thread context switch time and memory use
191–200 of 201 posts
Re: Comparison of Rust async and Linux thread context switch time and memory use
#192Earlier quoted context omitted.
The way you have quoted this suggests it is being said by the author, whom you are disagreeing with. It's not: it's being said by someone else (in an issue filed against the repo), and the author also mostly disagrees.
Indeed. I read it as something written by the author. Double-checking revealed it was written by spacejam that did post the same argumentation over and over here on HN.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#193Earlier quoted context omitted.
It seems to me that these are two orthogonal topics. One thing is how you represent tasks, either using OS threads or async tasks. And the other is how you structure concurrency. Maybe I'm missing something, but I think there is nothing preventing the use of those structured concurrency patterns using OS threads as the base for tasks. Then you get some nice benefits of doing this such as proper stack-traces and easie…
The advantage of async tasks for structured concurrency lies in task cancellation, which is intrinsically linked to the notion of "task ownership". If you are using an OS thread to offload some task, and then realize that you don't need that task's result anymore, your safest bet is to let the thread run until the end and then discard the results it produces. Other options include adding custom cancellation logic to…
Re: Comparison of Rust async and Linux thread context switch time and memory use
#194Earlier quoted context omitted.
> Ease of understanding multithreaded code Rust is not Javascript. Using threads is actually a lot simpler in Rust than async/await.
I don’t know about Rust but in every other language I’ve used threads were easy to use and understand, except when it came to some bits like signals, which at least on Linux are no longer a big problem. Main thread runs a hot loop to look for data to process, then hands it off on a queue to a worker thread out of a pool. That thread is then solely responsible for processing the event and passing the result either bac…
Re: Comparison of Rust async and Linux thread context switch time and memory use
#195Earlier quoted context omitted.
This is perfectly valid for NodeJS, Python (async and/or threads, hello GIL[0]), and a host of other languages/runtimes. Also I agree that multi-threaded Rust is probably the best alternative to async Rust. [0] I have no problems with the GIL, but it's yet another factor to consider when a python multi-threaded program stops working as intended
Not sure how you can compare then. You can’t do with the threads what you can do with async functions.
You can do exactly the same thing, after all async is just a big auto-generated state-machine that puts jobs onto a thread pool and waits for them.
Nginx is hand crafted (artisanal!) event-driven C, which is exactly how async runtimes also work. A big loop (the event loop, usually an infinite `while` blocked on epoll()). For example NodeJS uses libuv for this.
The big advantage of first class async support is that we don't have to do this by hand. Plus it makes some optimizations easier (eg. putting things on the stack instead of assigning each event handler a slice of some global [heap allocated] structure).
Or maybe I'm simply misunderstanding what you meant. In that case cloud you clarify please?
Re: Comparison of Rust async and Linux thread context switch time and memory use
#196The problem with threads is you need to correctly size your thread pool. That's hugely difficult if you have unknown lengths of blocking IO.
what kind of problem were you trying to solve that you found sizing a thread pool to be difficult? generally when I've worked on high performance server code I've been coding with a target machine in mind, so it's more a matter of mapping the thread pool size to the resources available on that machine. but I'm interested to hear about circumstances where it wouldn't be easy.
If you add a huge thread pool, and then those downstreams don't have a large latency, then you end up accepting a huge amount of work and then are CPU starved.
So in order to correctly size your thread pool, you need to understand all your downstream latency, and adapt to it.
Compared to an async runtime, which just handles this scenario, it's very painful.
Even if you get this roughly right, the scheduler is very unhappy when you have lots of threads - it tends to make incorrect scheduling decisions.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#197Earlier quoted context omitted.
yeah, the original example is showing the unwieldy version of the syntax.
The original example by me did not assume that asynchronous functions all return the same result type. Mist opportunities for concurrency are between unrelated tasks (because related tasks often dependencies between them). Unrelated tasks tend to have unrelated return types.
var p_t = GetUserPermission(username);
var c_t = GetServerConfig();
var m_t = GetMessageOfTheDay();
function_to_call1(await p_t, await c_t);
function_to_call2(await m_t);
This does not look any more complicated than a non-async function. Not sure how this example justifies your claims.Besides, even if your example is valid, the usage of Task.WhenAll has nothing to do with your claims either. The use of async/await is majorly for scalability. Being able to make several network calls concurrently is not the major concern. Even if you await at each async call, you still achieve better scalability because threads won't be blocked for async calls and can work on something else.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#198Earlier quoted context omitted.
I have done benchmarking on a linux laptop. Once you disable turbo-boost you get quite consistent results for CPU-bound tasks at least.
You have to do so much more to be able to reliably measure events on the scale of nanos. You need to lock C-states, disable P-state driver, isolate CPUs, get rid of RCUs, affinitize your tasks, enable low-tick mode, skew hr ticks, make sure you use TSC clocksource, set the cpu governor, get rid of vmstat, set correct idle driver, disable audits, and watchdogs and much, much more.
Re: Comparison of Rust async and Linux thread context switch time and memory use
#199Earlier quoted context omitted.
My teams/company uses it all over, so maybe depends on the context you work in? And FWIW, this explicit form is often unnecessary - if you kick off each task they will run in parallel and then just await each task only when the result is needed, it can look a lot cleaner: var p_t = GetUserPermission(username); var c_t = GetServerConfig(); var m_t = GetMessageOfTheDay(); var foo = isAuthorized(await p_t); // more code…
True, this doesn't work in Rust though, because nothing at all happens before the first time you poll a future, so you need an explicit task (but as other pointed out, it's pretty straightforward thanks to the `join!` macro).
Re: Comparison of Rust async and Linux thread context switch time and memory use
#200Earlier quoted context omitted.
It's a runtime for running lightweight tasks (`Future`s, async functions) on top of it. What is not async about it? And of course it still needs posix threads. The executor needs to run somewhere, and the only somewhere that an OS offers is a thread.
Sure, but I didn't think anything about async functions implied running tasks. Isn't it just syntactic sugar over futures? You certainly don't need to use the tokio runtime in order to use async functions. So, it's not clear why you'd abandon the async syntax just because you're compute bound.