展开描述
改进协作调度的实用工具。
§Cooperative scheduling
对顶层任务的一次 poll 调用在返回 Poll::Pending 之前可能会做大量工作。如果任务长时间运行而不让步回执行器,则会饿死等待该执行器执行它们的其他任务,或无法驱动底层资源。由于 Rust 没有运行时,因此很难强制抢占长时间运行的任务。相反,此模块提供了一种 opt-in 机制,让 future 与执行器协作以避免饥饿。
考虑这样的 future:
async fn drop_all<I: Stream + Unpin>(mut input: I) {
while let Some(_) = input.next().await {}
}它看起来无害,但考虑在高负载下如果输入流始终就绪会发生什么。如果我们生成 drop_all,任务将永远不会让步,并会饿死同一执行器上的其他任务和资源。
为了解决此问题,Tokio 在许多库函数中具有显式的让步点,强制任务定期返回到执行器。
§unconstrained
如有必要,task::unconstrained 允许你将 future 从 Tokio 的协作调度中排除。当 future 使用 unconstrained 包装时,它将永远不会被强制让步给 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
- Future wrapper to ensure cooperative scheduling created by
cooperative. - Restore
OnPending - Value returned by the
poll_proceedmethod. - Unconstrained
- Future for the
unconstrainedmethod.
函数§
- consume_
budget - Consumes a unit of budget and returns the execution back to the Tokio runtime if the task’s coop budget was exhausted.
- cooperative
- Creates a wrapper future that makes the inner future cooperate with the Tokio scheduler.
- has_
budget_ remaining - Returns
trueif there is still budget left on the task. - poll_
proceed - Decrements the task budget and returns
Poll::Pendingif the budget is depleted. This indicates that the task should yield to the scheduler. Otherwise, returnsRestoreOnPendingwhich can be used to commit the budget consumption. - unconstrained
- Turn off cooperative scheduling for a future. The future will never be forced to yield by Tokio. Using this exposes your service to starvation if the unconstrained future never yields otherwise.