I learned that async run lazily as it only run when the thread is idle. But is it possible for async to spawn thread and run parallel if the server has multi core cpu ?
Where did you learn this? This is false.
Not sure what do you mean by this, but I'll give it a try nonetheless:
Async is for IO-heavy tasks, not for CPU-intensive tasks. If you want something to run in parallel, don't use async. In Rust, async runtimes such as Tokio provide specific APIs and a threadpool for running CPU-intensive tasks, precisely so that these don't block the threads dedicated for running the async tasks.
Probably better to think about Rust async as the language feature, which simply allows incremental progress on some code, and async executors, like tokio
, separately.
For an executor to be able to run a Future
on multiple threads requires that the Future
and it's Output
implement Send
, which means it can (roughly) be sent to another thread safely. For example, see the where bounds on Tokio spawn()
The thing that determines whether the Future
returned from your async code implements Send
is essentially whether you hold anything that isn't Send
across an .await
, for example a mutex lock.
Future
s that aren't Send
safe often called local futures, so the equivalent single thread API is often named that, for example Tokio's LocalSet
allows handling multiple local futures on the same thread safely.
This is my understanding of async, parallel, and what we have in Rust (my usage of certain terms may not be super accurate -- e.g. what's a "task").
Imagine a restaurant, where you have employees preparing meals.
- An employee can make one meal, put it in the oven, wait till it's done, then give it to the customer.
- The employee can then make another meal. This is serial execution.
- To save time, the employee, while meal 1 is in the oven, can go and work on meal 2.
- This is what we call
async
. - Making a meal comprises of many parts, some may need your attention (e.g. using a knife), others may not (e.g. wait for food blender / oven).
- While steps continue to require an employee's attention, their attention is always on one meal.
- When they encounter a step that they have to wait, they can switch their attention to another meal. These are the
.await
points. - In Rust, a task is (usually) a series of CPU steps, until the code runs some IO.
- Parallelism is when you have more than one employees making more than one meal.
- A
Future
isSend
if different employees can work on the same meal -- i.e. employee A put meal 1 in the oven, but employee B took it out and delivered it. - If a
Future
is not Send, then the same employee has to come back and continue making the meal. tokio
is one such "restaurant", and the current-thread flavour runs with one employee, and the multi-thread flavour runs with multiple employees.tokio::task::spawn
is like an employee sending a special order to dedicated employees who prepare meals that need full attention for extended periods of time.- That's because if you take away a front line employee's attention for too long, the orders pile up.
someone else can probably continue this
I think your point 13 is supposed to be spawn_blocking or something? Otherwise I'm not sure I understand what the metaphor is trying to say - spawn is the standard API to "start an order"