mirror of
https://github.com/darkicewolf50/RustBrock.git
synced 2025-06-15 13:04:18 -06:00
finshed ch17 intro
This commit is contained in:
parent
6e94e27e06
commit
20d58f8ef5
22
.obsidian/workspace.json
vendored
22
.obsidian/workspace.json
vendored
@ -49,6 +49,20 @@
|
|||||||
"title": "Async, Await, Futures and Streams"
|
"title": "Async, Await, Futures and Streams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "6142f6650517896f",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "Futures and Async.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "Futures and Async"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "2a974ca5442d705f",
|
"id": "2a974ca5442d705f",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
@ -102,7 +116,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentTab": 2
|
"currentTab": 3
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "vertical"
|
"direction": "vertical"
|
||||||
@ -245,10 +259,11 @@
|
|||||||
"command-palette:Open command palette": false
|
"command-palette:Open command palette": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "42d65c7d3f15198d",
|
"active": "6142f6650517896f",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"Concurrency.md",
|
|
||||||
"Async, Await, Futures and Streams.md",
|
"Async, Await, Futures and Streams.md",
|
||||||
|
"Futures and Async.md",
|
||||||
|
"Concurrency.md",
|
||||||
"Shared State Concurrency.md",
|
"Shared State Concurrency.md",
|
||||||
"Sync and Send.md",
|
"Sync and Send.md",
|
||||||
"().md",
|
"().md",
|
||||||
@ -273,7 +288,6 @@
|
|||||||
"Modules.md",
|
"Modules.md",
|
||||||
"Generic Types Traits and Lifetimes.md",
|
"Generic Types Traits and Lifetimes.md",
|
||||||
"Generics.md",
|
"Generics.md",
|
||||||
"Lifetimes.md",
|
|
||||||
"does_not_compile.svg",
|
"does_not_compile.svg",
|
||||||
"Untitled.canvas",
|
"Untitled.canvas",
|
||||||
"Good and Bad Code/Commenting Pratices",
|
"Good and Bad Code/Commenting Pratices",
|
||||||
|
@ -1 +1,133 @@
|
|||||||
# Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams
|
# Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams
|
||||||
|
Many of the operations we ask computers to do can take a while to finish.
|
||||||
|
|
||||||
|
While waiting for that task it would be nice to do something else while we are waiting for those long-running processes to complete.
|
||||||
|
|
||||||
|
Modern computers offer two techniques while working on more than one operation at a time:
|
||||||
|
- Parallelism
|
||||||
|
- Concurrency
|
||||||
|
|
||||||
|
Once we start writing programs that involve parallel or concurrent operations, we quickly encounter new challenges inherit to *asynchronous programming*.
|
||||||
|
|
||||||
|
This is where operations may not finish sequentially in the order they were started.
|
||||||
|
|
||||||
|
This section builds on the use of threads for parallelism and concurrency by introducing an alternative approach to asynchronous programming.
|
||||||
|
|
||||||
|
Rust's Futures, Streams, the `async` and `await` syntax that supports them and the tools for managing and coordinating between asynchronous operations.
|
||||||
|
|
||||||
|
We will consider this example.
|
||||||
|
|
||||||
|
Say you are exporting a video you created of a family celebration, an operation that could take anywhere from minutes to hours.
|
||||||
|
|
||||||
|
The video export will use as many resources as available on the GPU and CPU.
|
||||||
|
|
||||||
|
If you only had one CPU core and your operating system didn't pause that export until it completed (it executed *synchronously*), you wouldn't be able to do anything else on the computer while that task was running.
|
||||||
|
|
||||||
|
This would be incredibly frustrating experience.
|
||||||
|
|
||||||
|
Fortunately, your computer's operating system can, and does, interrupt the export often enough to let you get other work done simultaneously.
|
||||||
|
|
||||||
|
In another scenario, say you are downloading a video from somewhere else, which can also take a while but does not take up as much CPU time.
|
||||||
|
|
||||||
|
In this case the CPU has to wait for data to arrive from the network.
|
||||||
|
|
||||||
|
While you can start reading the data once it starts to arrive, it may take some time for all of it to show up.
|
||||||
|
|
||||||
|
Even once the data us all present, if the video is quite large, it could take at least a second or two to load it all.
|
||||||
|
|
||||||
|
The video export is an example of a *CPU-bound* or *compute-bound* operation.
|
||||||
|
|
||||||
|
It is limited by the computer's potential data processing speed within the CPU or GPU, and how much speed it can dedicate to the operation.
|
||||||
|
|
||||||
|
The video download is an example of a *IO-bound* operation because it is limited by the speed of the computer's *input and output*; it can only go as fast as the data can be sent across the network.
|
||||||
|
|
||||||
|
In both of these examples, the operating system's invisible interrupts provide a form of concurrency.
|
||||||
|
|
||||||
|
This concurrency happens only at the level of the entire program: the operating system interrupts one program to let other programs get work done.
|
||||||
|
|
||||||
|
In many cases, because we understand our programs at a much more granular level than the OS does, we can spot opportunities for concurrency that the operating system can't see.
|
||||||
|
|
||||||
|
Lets say we are building a tool to manage file downloads, we should be able to write our program so that starting one download won't lock up the UI, and users should be able to start multiple downloads at the same time.
|
||||||
|
|
||||||
|
Many operating system API's for interacting with the network are *blocking*; that is they block the program's progress until the data they are processing is completely ready.
|
||||||
|
|
||||||
|
Note: This is how *most* functions calls work.
|
||||||
|
|
||||||
|
However, the term *blocking* is usually reserved for function calls that interact with files, the network, or other computer resources.
|
||||||
|
|
||||||
|
Due to these cases where an individual program would benefit from the operation being *non*-blocking.
|
||||||
|
|
||||||
|
We could avoid blocking our main thread by spawning a dedicated thread to download each file.
|
||||||
|
|
||||||
|
The overhead of those threads would eventually become a problem.
|
||||||
|
|
||||||
|
It would be preferable if the call didn't block it in the first place, it would be better if we could write in the same style we use in blocking code.
|
||||||
|
|
||||||
|
This would be a similar case/code
|
||||||
|
```rust
|
||||||
|
let data = fetch_data_from(url).await;
|
||||||
|
println!("{data}");
|
||||||
|
```
|
||||||
|
This is example what Rust's async (short for *asynchronous*) abstraction gives us.
|
||||||
|
|
||||||
|
This chapter we will learn about:
|
||||||
|
- Futures and Async Syntax [Section Link Here](./Futures%20and%20Async.md)
|
||||||
|
- How to use Rust's `async` and `await` syntax [Section Link Here]()
|
||||||
|
- How to use the async model to solve some of the same challenges we looked at in Ch 16 [Section Link Here]()
|
||||||
|
- How multithreading and async provide complementary solutions, that you can combine in many cases [Section Link Here]()
|
||||||
|
Before jumping into how async works in practice, we need o take a short detour to discuss the differences between parallelism and concurrency.
|
||||||
|
|
||||||
|
## Parallelism and Concurrency
|
||||||
|
So far we treated parallelism and concurrency as mostly interchangeable so far.
|
||||||
|
|
||||||
|
Now we need to distinguish between them more precisely, because the differences will now start to show up.
|
||||||
|
|
||||||
|
Consider the different ways a team could split up work on a software project.
|
||||||
|
|
||||||
|
You could assign a single member multiple tasks assign each member one task or use a mix of the two approaches.
|
||||||
|
|
||||||
|
When an individual works on several different tasks before any of them is complete, this is *concurrency*.
|
||||||
|
|
||||||
|
Or maybe you have two different projects checked out on your computer and when you get bored or stuck on one project, you switch to the other.
|
||||||
|
|
||||||
|
As one person, so you can't make progress on both tasks at the exact same time, but you can multi-task, making progress on one at a time by switching between them.
|
||||||
|
|
||||||
|
Here is a picture of this
|
||||||
|
<img src="https://doc.rust-lang.org/book/img/trpl17-01.svg" />
|
||||||
|
When the team instead splits up a group of tasks by having each member take one task and work on it alone, this is *parallelism*
|
||||||
|
|
||||||
|
Each person on the team can make progress at the exact same time.
|
||||||
|
<img src="https://doc.rust-lang.org/book/img/trpl17-02.svg" />
|
||||||
|
In both of these workflows, you might have to coordinate between different tasks.
|
||||||
|
|
||||||
|
Maybe it was *thought* that the task was totally independent from every other.
|
||||||
|
|
||||||
|
It actually requires another person on the team to finish their task first..
|
||||||
|
|
||||||
|
Some of this work can be done in parallel, but some of it actually was *serial*: it could only happen in a series, one task after another.
|
||||||
|
|
||||||
|
Here is a diagram of this
|
||||||
|
<img src="https://doc.rust-lang.org/book/img/trpl17-03.svg" />
|
||||||
|
Likewise, you may realize that one of your own tasks depends on another of your tasks.
|
||||||
|
|
||||||
|
Now your concurrent work has also become serial.
|
||||||
|
|
||||||
|
Parallelism and concurrency can intersect with each other as well.
|
||||||
|
|
||||||
|
If you learn that colleague is stuck until you finish one of your tasks, you will probably focus all your efforts to "unblock" you colleague.
|
||||||
|
|
||||||
|
You and your coworkers are no longer able to work in parallel, and you are also no longer able to work concurrently on the task assigned.
|
||||||
|
|
||||||
|
The same dynamics come into play with software and hardware.
|
||||||
|
|
||||||
|
On a CPU core, the CPU can perform only one operation at a time but it can still work concurrently.
|
||||||
|
|
||||||
|
Using tools such as threads, processes and async, the computer can pasue one set of calculations and switch to others before cycling back to that first set of calculations again.
|
||||||
|
|
||||||
|
One a machine with multiple CPU cores, it can also do work in parallel.
|
||||||
|
|
||||||
|
One core can be performing one task while another core performs a completely unrelated one, and those operations actually happen at the same time.
|
||||||
|
|
||||||
|
When working with async in Rust, we are always dealing with concurrency.
|
||||||
|
|
||||||
|
Depending on the hardware, OS and the async runtime we use (more on async runtimes shortly), that concurrency many also use parallelism under the hood.
|
||||||
|
1
Futures and Async.md
Normal file
1
Futures and Async.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Futures and the Async Syntax
|
Loading…
x
Reference in New Issue
Block a user