CPU는 I/O Bus보다 월등히 빠르기 때문에, 디바이스나 Bus로부터 R/W를 하기위해 오랜 시간을 기다려야 한다. 따라서 I/O bound task들은 asynchronous하게 수행/관리 되면 좋다.
Rust에서 IO bound task는 async/await
를 사용하는것이 더 유리하다. (의문: CPU bound task는 std::thread
를 사용하는것이 적합?) Embedded환경은 I/O연산이 많기 때문에, Embedded-rust 에서 aync/await를 사용하는 이유가 바로 이것. 다만 async는 executable 바이너리 사이즈를 더 증가시킬수 있다.
Thread를 spawning하고 switching하는 작업은 시스템의 리소스를 많이 사용하는 비용이 꽤 큰 작업이다. (Thread pool library를 사용하면 조금 개선이 가능). 몇 OS는 thread의 우선순위를 설정할 수 있기 때문에, latency가 중요한 task에는 thread가 도움이 될 수 있다. 반면 연산이 많지 않은 task들은 thread보다 async를 사용하는게 바람직 하다. Thread는 비용이 크기 때문.
두개의 웹 페이지를 다운로드 하는작업을 해보자. 아래와 같이 thread를 사용하면 시스템의 자원을 불필요하게 낭비 하는것과 같다. 웹 페이지를 다운로드하는 것은 작업량이 많지 않은 작은 task이기 때문.
fn get_two_sites() {
// Spawn two threads to do work.
let thread_one = thread::spawn(|| download("https://www.foo.com"));
let thread_two = thread::spawn(|| download("https://www.bar.com"));
// Wait for both threads to complete.
thread_one.join().expect("thread one panicked");
thread_two.join().expect("thread two panicked");
}
async를 사용하면 굳이 thread를 사용하지 않고도 더 효율적으로 작업할 수 있다.
async fn get_two_sites_async() {
// Create two different "futures" which, when run to completion,
// will asynchronously download the webpages.
let future_one = download_async("https://www.foo.com");
let future_two = download_async("https://www.bar.com");
// Run both futures to completion at the same time.
join!(future_one, future_two);
}