Rust 异步 IO

异步相比线程开销小,bug 没那么复杂

Future 类似 js 的 Promise,返回 impl Future
// 基于 poll(状态机,通知 Future 来取值) 而不是 callback(把值传过去),方便取消(?)
async fn foo(arg: &str) -> usize { ... }
// fn foo<'a>(arg: &'a str) -> impl Future + 'a { ... }
还引入了 Pin 用来解决一些引用问题 // 不可移动的对象可以在它们的字段之间存储指针
需要一个执行者来执行 Future // 如 futures crate
使用系统的 io 回调来检查 Future 是否完成

mio 提供的唯二两个核心功能分别是: // 类似 libuv,轮询 epoll
  • 对操作系统异步网络 IO 的封装
  • Linux(Android) => epoll
  • Windows => iocp
  • MacOS(iOS), FreeBSD => kqueue
  • Fuchsia => port
  • 用户自定义事件队列
// epoll 维护一个活动列表(想象成发生了变化的 fd 事件集,链结构),只需要遍历这个列表,而不需要遍历所有
// 使用系统提供的 epoll 可以减少内核态-用户态切换
// 内核收到数据,设置 fd ,标记状态


// 并发方案还有绿色线程,Actor 模型(线程池)

Rust’s approach to async I/O are:
  • Minimize system resources for handling a large number of concurrent I/O tasks
  • Provide a zero-cost abstraction on top of the async I/O mechanisms provided by operating systems
  • Do it at a library level, instead of introducing a runtime to Rust

Instead of doing the silly wasteful thing, the futures crate is far smarter. It has a mechanism to:
  • determine which task is trying to get access to the data provided by this future, and then
  • notify that task that new data is available
A Future is an action with a delayed single result. A Stream is a stream of results, like an Iterator, with a delay between each value.
Stream 有一个 for_each 用来执行函数,返回一个 Future(future::ok(())) 可以让 tokio::run
// js 的 Stream 也是生成多个 Promise

What if we want to process each directory concurrently? To do that, we need to spawn another task, the same way we would spawn a new thread. Like tokio::run, tokio::spawn takes a Future where both Item and Error are ().
// 一个任务有 future poll 顺序,多个任务可以一次 poll 多个 future
// The default executor is usually a thread pool.