3 ms·
Keep in mind that a new async task doesn't create a new thread. So yes, "not creating a new thread" is 3x faster than "creating a thread". If the app layer can
by harikb 6y ago
Keep in mind that a new async task doesn't create a new thread. So yes, "not creating a new thread" is 3x faster than "creating a thread". If the app layer can context switch using language level constructs, and do co-operative switching, then yes, one gets the 3x benefit. imho, whether the async executor and scheduler is performant enough to manage the tasks is what one should worry about.
- scoutt 6y agoI'm confused. If many async tasks are ran on a single thread, what the thread does when is blocked waiting for things to happen? Does it sleep? If so, a context switch takes place anyway. If not, what is the impact on GUI applications? If I have a main thread to manage my GUI, should I spin a new thread to run my async tasks? A modern microcontroller/microprocessor is inherently event driven (for example, on ARM, at the very bottom of the call stack there is a wait-for-event (WFE) or wait-for-interrupt (WFI) instruction). If async needs to be polled to run ("Futures are inert in Rust and make progress only when polled"[1]) this means my processor should be busy running these async tasks instead of waiting (WFE or WFI) as the result of a native call to one of the operating system functions (i.e. recv() on a socket). What is the impact on embedded battery-based systems? [1] https://rust-lang.github.io/async-book/01_getting_started/02_why_async.html#async-in-rust-vs-other-languages https://rust-lang.github.io/async-book/01_getting_started/02...
- jstrong 6y agoin rust, there is no built-in runtime, so it depends on which one you are using. the runtime (e.g. tokio) is responsible for polling the future. for network io, behind the scenes this is most likely utilizing epoll system calls. epoll mitigates context switch problem in a few ways, mostly because there is only one stack context to notify about new io events, instead of many.
- harikb 6y agopolling is only explained as a logical thing. In reality the given task is only marked to be woken up later. The later being some other point, while the same OS thread executing something else, when the executor determines that the idling task can be woken up. "Waking" is nothing but the same OS thread now switching to execute whatever it is that it is waking up. Main idea is that a 'scheduler/executor' at the runtime/language level that knows about the state of the program can (a) 'save' and 'restore' fewer things compared to an OS context switch. (b) co-operative stuff does not need to pay the cost of too many unnecessary pre-emptions
- scoutt 6y agoThanks. > polling is only explained as a logical thing But there is the poll() function that returns either the result of the operation, or "pending". So it's more than logical. Correct? I mean, if I (or the executor) don't call poll() nothing happens... > OS thread now switching to execute whatever it is that it is waking up. This is what confuses me. As I see it (and I what I understand from reading), async/await splits a routine into a (very smart) state machine. I assume that there is no magic underneath. I mean, I can do the same state machine by hand if I want to, under the constraints of what the OS makes available for me in what context switching regards (APIs for waiting and synchronizing). For a (OS/native) thread that has to wait for data on a socket, you have (basically) two options: wait on recv() or poll recv() without timeout. Waiting on recv() would block (so no other code of my thread can be executed while waiting), so I guess the state machine needs to poll on recv() (I believe this is what this[1] example does). In order to no block my thread, the executor either spins its own thread, or has to wait for my thread to poll() it. [1] https://rust-lang.github.io/async-book/02_execution/02_future.html https://rust-lang.github.io/async-book/02_execution/02_futur...
- bitcharmer 6y agoYou're only the second commenter on this thread to notice this. The benchmark compares fibers to threads and has little to do with Rust. You will see the same numbers for a fibers implementation in any natively compiled language like C or Java. The title is completely misleading, especially for most people who are not aware of this important distinction.