跳到主要内容

Module coop

搜索

Module coop 

源代码
展开描述

改进协作调度的实用工具。

§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.
RestoreOnPending
Value returned by the poll_proceed method.
Unconstrained
Future for the unconstrained method.

函数§

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 true if there is still budget left on the task.
poll_proceed
Decrements the task budget and returns Poll::Pending if the budget is depleted. This indicates that the task should yield to the scheduler. Otherwise, returns RestoreOnPending which 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.