展开描述
用于改进协作式调度的工具。
§Cooperative scheduling
对顶层任务的
poll
的一次调用可能会在返回
Poll::Pending 之前
做大量工作。
如果一个任务长时间运行
而不让出回 executor,
它可能会饿死正在该 executor 上
等待执行的其他任务,
或驱动底层资源。
由于 Rust 没有运行时,
强制抢占一个长时间运行的任务
是困难的。
相反,
本模块为 future 提供了一种
选择性加入的机制,
以与 executor 协作
以避免饥饿。
考虑这样一个 future:
async fn drop_all<I: Stream + Unpin>(mut input: I) {
while let Some(_) = input.next().await {}
}它可能看起来无害,
但考虑一下在高负载下
如果输入流始终就绪
会发生什么。
如果我们派生 drop_all,
任务将永远不会让出,
并将饿死同一 executor 上的
其他任务和资源。
为了解决这个问题,Tokio 在许多库函数中 具有显式的让出点,这些点强制任务周期性地返回到 executor。
§unconstrained
If necessary, task::unconstrained lets you opt a future out of Tokio’s cooperative
scheduling. When a future is wrapped with unconstrained, it will never be forced to yield to
Tokio. 例如:
use tokio::{task, sync::mpsc};
let fut = async {
let (tx, mut rx) = mpsc::unbounded_channel();
for i in 0..1000 {
let _ = tx.send(());
// This will always be ready. If coop was in effect, this code would be forced to yield
// periodically. However, if left unconstrained, then this code will never yield.
rx.recv().await;
}
};
task::coop::unconstrained(fut).await;结构体§
- Coop
- 由
cooperative创建的、用于保证协作式调度的 future 包装器。 - Restore
OnPending - 由
poll_proceed方法返回的值。 - Unconstrained
unconstrained方法对应的 future。
函数§
- consume_
budget - 消耗一个单位的预算;若 task 的协作预算已耗尽,则将执行权交回 Tokio 运行时。
- cooperative
- 创建一个包装 future,使内部 future 与 Tokio 调度器协作。
- has_
budget_ remaining - 如果 task 上还有剩余预算,则返回
true。 - poll_
proceed - 减少 task 预算;若预算已耗尽,则返回
Poll::Pending。这表示 task 应让出(yield)给调度器。其他wise, returnsRestoreOnPendingwhich can be used to commit the budget consumption. - unconstrained
- 关闭某个 future 的协作式调度。该 future 永远不会被 Tokio 强制让出。使用它会使你的服务面临饥饿(starvation)的风险,除非该 unconstrained future 自己会让出。