Async/.await

03 декември 2019

Async/await

Async/await

Async/await

Async/await

Async/await

Async/await

Защо async/await?

Проблемът

Конкурентност - искаме да изпълняваме няколко неща едновременно

1 2 3 4 5
fn main() -> io::Result<()> {
    let contents1 = read_file("file1.txt")?;
    let contents2 = read_file("file2.txt")?;
    // ...
}
use std::io;
fn read_file(path: &str) -> io::Result { unimplemented!() }

fn main() -> io::Result<()> {
    let contents1 = read_file("file1.txt")?;
    let contents2 = read_file("file2.txt")?;
    // ...
Ok(())
}

Защо async/await?

Решение

Нишки

1 2 3 4 5 6 7 8
fn main() -> io::Result<()> {
    let t1 = thread::spawn(|| read_file("file1.txt"));
    let t2 = thread::spawn(|| read_file("file2.txt"));

    let contents1 = t1.join().unwrap()?;
    let contents2 = t2.join().unwrap()?;
    // ...
}
use std::io;
use std::thread;
fn read_file(path: &str) -> io::Result { unimplemented!() }

fn main() -> io::Result<()> {
    let t1 = thread::spawn(|| read_file("file1.txt"));
    let t2 = thread::spawn(|| read_file("file2.txt"));

    let contents1 = t1.join().unwrap()?;
    let contents2 = t2.join().unwrap()?;
    // ...
Ok(())
}

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Защо async/await?

Нишки

Async/await в Rust

1 2 3 4
# Cargo.toml

[dependencies]
async-std = "1.1.0"

Async/await в Rust

Std

1 2 3 4 5 6 7 8 9 10 11
use std::fs::File;
use std::io::{self, Read};



fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;
    Ok(buffer)
}
use std::fs::File;
use std::io::{self, Read};



fn read_file(path: &str) -> io::Result {
    let mut file = File::open(path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;
    Ok(buffer)
}

fn main() {}

Async/await в Rust

Async-std

1 2 3 4 5 6 7 8 9 10 11
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;


async fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path).await?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;


async fn read_file(path: &str) -> io::Result {
    let mut file = File::open(path).await?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}

fn main() {}

Async/await в Rust

`async fn`

1 2 3 4 5 6 7 8 9 10 11
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

// async fn декларира, че това е асинхронна функция, която връща Future
async fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path).await?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

// async fn декларира, че това е асинхронна функция, която връща Future
async fn read_file(path: &str) -> io::Result {
    let mut file = File::open(path).await?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}

fn main() {}

Async/await в Rust

Груб превод на `async fn`

async fn(...) -> Tfn(...) -> impl Future<Output = T>

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

use std::future::Future;

fn read_file<'a>(path: &'a str) -> impl Future<Output = io::Result<String>> + 'a {
    // async блок също връща `impl Future`
    async move {
        let mut file = File::open(path).await?;
        let mut buffer = String::new();
        file.read_to_string(&mut buffer).await?;
        Ok(buffer)
    }
}
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

use std::future::Future;

fn read_file<'a>(path: &'a str) -> impl Future> + 'a {
    // async блок също връща `impl Future`
    async move {
        let mut file = File::open(path).await?;
        let mut buffer = String::new();
        file.read_to_string(&mut buffer).await?;
        Ok(buffer)
    }
}

fn main() {}

Trait Future

1 2 3 4 5 6 7 8 9
pub trait Future {
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output>;
}

pub enum Poll<T> {
    Ready(T),
    Pending,
}
use std::task::Context;
use std::pin::Pin;

pub trait Future {
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll;
}

pub enum Poll {
    Ready(T),
    Pending,
}

fn main() {}

Trait Future

Trait Future

Trait Future

Trait Future

Trait Future

Trait Future

std::future и futures-rs

std::future и futures-rs

std::future и futures-rs

std::future и futures-rs

std::future и futures-rs

std::future и futures-rs

Async/await в Rust

.await

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

async fn read_file(path: &str) -> io::Result<String> {
    // File::open() -> impl Future<Output=Result<File, io::Error>>
    // .await       -> Result<File, io::Error>
    // ?            -> File
    let mut file = File::open(path).await?;

    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;

async fn read_file(path: &str) -> io::Result {
    // File::open() -> impl Future>
    // .await       -> Result
    // ?            -> File
    let mut file = File::open(path).await?;

    let mut buffer = String::new();
    file.read_to_string(&mut buffer).await?;
    Ok(buffer)
}

fn main() {}

Изпълнение

Има два начина да изпълним future

Задачи

Задачи

Задачи

Синхронно изпълнение

Задачи

Синхронно изпълнение

Задачи

Синхронно изпълнение

Задачи

Синхронно изпълнение

1 2 3 4 5
use async_std::task;
fn main() {
    let file_contents = task::block_on(read_file("deep_quotes.txt"));
    println!("{:?}", file_contents);
}
Ok("Failure is just success rounded down, my friend!\n")
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

fn main() {
let file_contents = "Failure is just success rounded down, my friend!\n";
std::fs::write("deep_quotes.txt", file_contents.as_bytes()).unwrap();
    let file_contents = task::block_on(read_file("deep_quotes.txt"));
    println!("{:?}", file_contents);
}

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

Задачи

Асинхронно изпълнение

1 2 3 4 5 6 7 8 9 10 11 12
use async_std::task;
fn main() {
    let file_contents = task::block_on(async {
        let deep_handle = task::spawn(read_file("deep_quotes.txt"));
        let wide_handle = task::spawn(read_file("wide_quotes.txt"));

        let deep = deep_handle.await;
        let wide = wide_handle.await;

        println!("All quotes:\n{:?}\n{:?}", deep, wide);
    });
}
All quotes: Ok("Failure is just success rounded down, my friend!\n") Ok("F a i l u r e i s j u s t s u c c e s s r o u n d e d d o w n , m y f r i e n d !\n")
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

fn main() {
let deep_contents = "Failure is just success rounded down, my friend!\n";
let wide_contents = "F a i l u r e  i s  j u s t  s u c c e s s  r o u n d e d  d o w n ,  m y  f r i e n d !\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
    let file_contents = task::block_on(async {
        let deep_handle = task::spawn(read_file("deep_quotes.txt"));
        let wide_handle = task::spawn(read_file("wide_quotes.txt"));

        let deep = deep_handle.await;
        let wide = wide_handle.await;

        println!("All quotes:\n{:?}\n{:?}", deep, wide);
    });
}

Конкурентност и паралелизъм

Конкурентност и паралелизъм

Конкурентност - много задачи се изпълняват върху една нишка, като се редуват за резен от процесорното време

Конкурентност и паралелизъм

Конкурентност - много задачи се изпълняват върху една нишка, като се редуват за резен от процесорното време
Паралелизъм - много задачи се изпълняват по едно и също време върху много нишки

Примери

Примери

1 2 3 4 5 6 7
use async_std::task;
use std::time::Duration;

async fn fetch_file(path: &str) -> io::Result<String> {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;
use std::time::Duration;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
fn main() {}

Примери

1 2 3 4 5 6 7
use async_std::task;
use std::time::Duration;

async fn fetch_file(path: &str) -> io::Result<String> {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;
use std::time::Duration;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
fn main() {}

Примери

1 2 3 4 5 6 7
use async_std::task;
use std::time::Duration;

async fn fetch_file(path: &str) -> io::Result<String> {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;
use std::time::Duration;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
fn main() {}

Примери

1 2 3 4 5 6 7
use async_std::task;
use std::time::Duration;

async fn fetch_file(path: &str) -> io::Result<String> {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;
use std::time::Duration;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
fn main() {}

Примери

1 2 3 4 5 6 7
use async_std::task;
use std::time::Duration;

async fn fetch_file(path: &str) -> io::Result<String> {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;
use std::time::Duration;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
    task::sleep(Duration::from_secs(1)).await;
    read_file(path).await
}
fn main() {}

Примери

1 2 3 4 5 6 7 8 9 10
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = fetch_file("deep_quotes.txt").await;
    let wide = fetch_file("wide_quotes.txt").await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.002997323s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = fetch_file("deep_quotes.txt").await;
    let wide = fetch_file("wide_quotes.txt").await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери

1 2 3 4 5 6 7 8 9 10
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = fetch_file("deep_quotes.txt").await;
    let wide = fetch_file("wide_quotes.txt").await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.002997323s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = fetch_file("deep_quotes.txt").await;
    let wide = fetch_file("wide_quotes.txt").await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let deep = deep_future.await;
    let wide = wide_future.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.00271393s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let deep = deep_future.await;
    let wide = wide_future.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let deep = deep_future.await;
    let wide = wide_future.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.00271393s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let deep = deep_future.await;
    let wide = wide_future.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - конкурентност

1 2 3 4 5 6 7 8 9 10 11 12 13 14
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.001517179s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
use futures::join;

let begin = std::time::Instant::now();

task::block_on(async {
    let deep_future = fetch_file("deep_quotes.txt");
    let wide_future = fetch_file("wide_quotes.txt");

    let (deep, wide) = join!(deep_future, wide_future);

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - паралелизъм

1 2 3 4 5 6 7 8 9 10
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = task::spawn(fetch_file("deep_quotes.txt")).await;
    let wide = task::spawn(fetch_file("wide_quotes.txt")).await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.003720327s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = task::spawn(fetch_file("deep_quotes.txt")).await;
    let wide = task::spawn(fetch_file("wide_quotes.txt")).await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - паралелизъм

1 2 3 4 5 6 7 8 9 10
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = task::spawn(fetch_file("deep_quotes.txt")).await;
    let wide = task::spawn(fetch_file("wide_quotes.txt")).await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 2.003720327s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep = task::spawn(fetch_file("deep_quotes.txt")).await;
    let wide = task::spawn(fetch_file("wide_quotes.txt")).await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - паралелизъм

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(fetch_file("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.002705287s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(fetch_file("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Примери - паралелизъм

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(fetch_file("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.002705287s
extern crate async_std;
use async_std::prelude::*;
use async_std::fs::File;
use async_std::io;
use async_std::task;

async fn read_file(path: &str) -> io::Result {
let mut file = File::open(path).await?;

let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(fetch_file("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Справяне с блокиращи операции

1 2 3 4
fn fetch_file_sync(path: &str) -> io::Result<String> {
    thread::sleep(Duration::from_millis(1500));
    read_file_sync(path)
}
use std::fs::File;
use std::io::{self, Read};
use std::thread;
use std::time::Duration;

fn read_file_sync(path: &str) -> io::Result {
let mut file = File::open(path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
Ok(buffer)
}

fn fetch_file_sync(path: &str) -> io::Result {
    thread::sleep(Duration::from_millis(1500));
    read_file_sync(path)
}
fn main() {}

Справяне с блокиращи операции

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn_blocking(|| fetch_file_sync("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.500905977s
extern crate async_std;
use async_std::prelude::*;
use async_std::task;
use std::io::Read as _;

async fn read_file(path: &str) -> async_std::io::Result {
let mut file = async_std::fs::File::open(path).await?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> async_std::io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn read_file_sync(path: &str) -> std::io::Result {
let mut file = std::fs::File::open(path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
Ok(buffer)
}

fn fetch_file_sync(path: &str) -> std::io::Result {
std::thread::sleep(std::time::Duration::from_millis(1500));
read_file_sync(path)
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn_blocking(|| fetch_file_sync("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Справяне с блокиращи операции

1 2 3 4 5 6 7 8 9 10 11 12 13
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn_blocking(|| fetch_file_sync("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Ok("W i d e!\n") Работата отне: 1.500905977s
extern crate async_std;
use async_std::prelude::*;
use async_std::task;
use std::io::Read as _;

async fn read_file(path: &str) -> async_std::io::Result {
let mut file = async_std::fs::File::open(path).await?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> async_std::io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn read_file_sync(path: &str) -> std::io::Result {
let mut file = std::fs::File::open(path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
Ok(buffer)
}

fn fetch_file_sync(path: &str) -> std::io::Result {
std::thread::sleep(std::time::Duration::from_millis(1500));
read_file_sync(path)
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn_blocking(|| fetch_file_sync("wide_quotes.txt"));

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Справяне с блокиращи операции

Вариант за ръчна имплементация, ако нямаше task::spawn_blocking

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(async {
        let (sender, receiver) = async_std::sync::channel(1);
        std::thread::spawn(move || {
            let res = fetch_file_sync("wide_quotes.txt");
            task::block_on(sender.send(res));
        });

        receiver.recv().await
    });

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
All quotes: Ok("Deep!\n") Some(Ok("W i d e!\n")) Работата отне: 1.501117439s
extern crate async_std;
use async_std::prelude::*;
use async_std::task;
use std::io::Read as _;

async fn read_file(path: &str) -> async_std::io::Result {
let mut file = async_std::fs::File::open(path).await?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)
}

async fn fetch_file(path: &str) -> async_std::io::Result {
task::sleep(std::time::Duration::from_secs(1)).await;
read_file(path).await
}

fn read_file_sync(path: &str) -> std::io::Result {
let mut file = std::fs::File::open(path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
Ok(buffer)
}

fn fetch_file_sync(path: &str) -> std::io::Result {
std::thread::sleep(std::time::Duration::from_millis(1500));
read_file_sync(path)
}

fn main() {
let deep_contents = "Deep!\n";
let wide_contents = "W i d e!\n";
std::fs::write("deep_quotes.txt", deep_contents.as_bytes()).unwrap();
std::fs::write("wide_quotes.txt", wide_contents.as_bytes()).unwrap();
let begin = std::time::Instant::now();

task::block_on(async {
    let deep_handle = task::spawn(fetch_file("deep_quotes.txt"));
    let wide_handle = task::spawn(async {
        let (sender, receiver) = async_std::sync::channel(1);
        std::thread::spawn(move || {
            let res = fetch_file_sync("wide_quotes.txt");
            task::block_on(sender.send(res));
        });

        receiver.recv().await
    });

    let deep = deep_handle.await;
    let wide = wide_handle.await;

    println!("All quotes: {:?} {:?}", deep, wide);
});

println!("Работата отне: {:?}", begin.elapsed());
}

Имплементация на futures

Стандартен стек

Стандартен стек

Стандартен стек

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Как работят

Stackfull coroutine

Как работят

Stackfull coroutine

Как работят

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Stackfull coroutine

Предимства

Недостатъци

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Как работят

Stackless coroutines

Как работят

Stackless coroutines

Как работят

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Stackless coroutines

Предимства

Недостатъци

Разгъване на .await

1 2 3 4
let mut file = File::open(path).await?;
let mut buffer = String::new();
file.read_to_string(&mut buffer).await?;
Ok(buffer)

Разгъване на .await

1 2 3 4 5 6 7 8 9 10
fn read_file(path: &str) -> ReadFileFut {
    ReadFileFut::Initialized { path }
}

enum ReadFileFut<'a> {
    Initialized { path: &'a str },
    FileOpen { fut: FileOpenFut },
    ReadToString { file: File, buffer: String, fut: ReadToStringFut },
    Done,
}
use async_std::fs::File;

fn read_file(path: &str) -> ReadFileFut {
    ReadFileFut::Initialized { path }
}

enum ReadFileFut<'a> {
    Initialized { path: &'a str },
    FileOpen { fut: FileOpenFut },
    ReadToString { file: File, buffer: String, fut: ReadToStringFut },
    Done,
}

struct FileOpenFut;
struct ReadToStringFut;

fn main() {}

Разгъване на .await

1 2 3 4 5 6 7 8 9 10 11 12 13 14
impl<'a> Future for ReadFileFut<'a> {
    type Output = io::Result<String>;

    fn poll(self: Pin<&mut Self>, _ctx: Context) -> Poll<Self::Output> {
        loop {
            match self {
                ReadFileFut::Initialized { .. } => { /* ... */ },
                ReadFileFut::FileOpen { .. } => { /* ... */ },
                ReadFileFut::ReadToString { .. } => { /* ... */ },
                ReadFileFut::Done => { /* ... */ },
            }
        }
    }
}

Разгъване на .await

Initialized { path }

Разгъване на .await

Initialized { path }

Разгъване на .await

FileOpen { fut }

Разгъване на .await

FileOpen { fut }

Разгъване на .await

ReadToString { buffer, fut, .. }

Разгъване на .await

ReadToString { buffer, fut, .. }

Разгъване на .await

ReadFileFut::Done

Разгъване на .await

ReadFileFut::Done

Обобщение

Обобщение

Обобщение

Обобщение

Обобщение

Обобщение

Обобщение

Обобщение

Допълнителна информация

Въпроси