新的Timer实现

祝所有人快乐!

为了结束一个伟大的一周,有一个[新发布]的Tokio。这个版本 包括一个全新的计时器实现。

定时器

有时(通常),人们想要执行与时间相关的代码。也许是 功能需要在特定时刻运行。也许阅读需要有限 到固定的时间。为了处理时间,需要访问计时器!

历史

tokio-timer箱子已经存在了一段时间。它最初建成 使用[哈希定时器轮] [轮](pdf警告)。它的粒度为100 毫秒,因此任何超时设置的分辨率都小于100毫秒 会被围捕。通常,在基于网络的应用程序的上下文中, 这可以。超时通常至少30秒,并不需要很高 精确。

但是,有些情况下100毫秒太粗糙。而且, Tokio计时器的原始实现有一些恼人的错误,但没有 由于实施策略,处理边缘案例非常好。

一个新的开始

计时器已从头开始重写并作为[tokio-timer发布 0.2] 2。在大多数情况下,API非常相似,但实现是 完全不同。

它不使用单个哈希定时器轮实现,而是使用 分层方法(也在上面链接的论文中描述)。

计时器使用六个不同的级别。每个级别都是一个包含64的散列轮 插槽。最低级别的插槽代表一毫秒。该 下一级别表示64毫秒(1 x 64个插槽),依此类推。所以,一个插槽 每个级别的时间与下面的整个级别相同。

设置超时后,如果距离当前时刻64毫秒内, 它处于最低水平。如果超时在64毫秒和4,096之间 毫秒,它进入第二级,依此类推。

随着时间的推移,最低级别的超时被触发。一旦结束了 达到最低级别,从中删除下一级别的所有超时 水平并移至最低水平。

使用此策略,所有计时器操作(创建超时,取消a 超时,触发超时)是不变的。这导致非常好的性能 即使有很多突出的超时。

快速浏览一下API

如上所述,API并没有真正改变。主要有三个 类型:

  • Delay:在设定的时刻完成的未来。
  • Deadline:装饰一个未来,确保它在之前完成   截止日期已到达。
  • Interval:以固定间隔产生值的流。

还有一个简单的例子:

use tokio::prelude::*;
use tokio::timer::Delay;

use std::time::{Duration, Instant};

fn main() {
    let when = Instant::now() + Duration::from_millis(100);
    let task = Delay::new(when)
        .and_then(|_| {
            println!("Hello world!");
            Ok(())
        })
        .map_err(|e| panic!("delay errored; err={:?}", e));

    tokio::run(task);
}

上面的例子创建了一个新的Delay实例,它将完成100 将来的毫秒数。 new函数接受Instant,所以我们计算 when是从现在起100毫秒的瞬间。

一旦到达瞬间,“延迟”未来就会完成,从而产生 and_then块被执行。

此版本附带一个简短的[指南],解释如何使用计时器和[API 文档】API

集成在运行时中

使用计时器API需要运行计时器实例。 Tokio [运行时] 为您完成所有设置。

当使用tokio :: run或通过调用Runtime :: new启动运行时 直接启动线程池。每个工作线程将获得一个计时器 实例。所以,这意味着如果运行时启动了4个工作线程,那么就会有 是4个计时器实例,每个线程一个。这样做可以不使用计时器 支付同步成本,因为计时器将位于同一个线程上 作为使用各种计时器类型的代码(DelayDeadlineInterval)。

有了这个,周末愉快!