Tokio 0.1.8 包含多项增量改进
2018年8月24日
新版本的 Tokio 发布了,虽然比我最初希望的时间晚了一些(总是这样),但还是发布了。此版本除其他功能外,还包括一组新的 API,允许从异步上下文执行文件系统操作、并发改进、定时器改进以及更多内容(包括错误修复,请务必更新!)。
自从上一篇文章以来已经有一段时间了。虽然没有重大的功能发布,但这并不意味着我们一直闲着。在过去的几个月里,新的 crates 已经发布,其中包含许多增量改进。这些改进中有许多是由社区贡献的,所以我认为有必要重点介绍一下。
文件系统 API
tokio-fs
的初始版本更像是一个存根,而不是完整的实现。它只包含基本的文件系统操作。
最新版本包含了大多数文件系统 API 的 非阻塞版本。这项了不起的工作主要由 @griff 在一个 史诗般的 PR 中以及 @lnicola 在一系列较小的 PR 中贡献,但许多其他人也参与了帮助审查和改进 crate。
感谢以下人员:@dekellum、@matsadler、@debris、@mati865、@lovebug356、@bryanburgers、@shepmaster。
并发改进
在过去的几个月里,@stjepang 一直在努力改进 Tokio 中与并发相关的部分。一些亮点:
- #459 - 修复线程唤醒中的竞争条件
- #470 - 改进 worker spinning
- #517 - 提高 reactor 中使用的 RW Lock 的可扩展性。
- #534 - 改进 work-stealing 运行时的 “stealing” 部分。
当他在城里参加 Rustconf 时,我们还进行了一次愉快的交流,我对他未来的工作感到兴奋。
当然,还要感谢所有的 crossbeam 工作。Tokio 非常依赖它。
current_thread::Runtime
自最初由 @vorner 和 @kpp 引入以来,current_thread::Runtime
也进行了一些增量改进。
@sdroege 添加了一个 Handle
,允许从其他线程将任务 spawn 到 runtime 上 (#340)。这是通过使用 channel 将任务发送到 runtime 线程来实现的(与 tokio-core
使用的策略类似)。
并且 @jonhoo 实现了 block_on_all
函数 (#477) 并修复了一个关于跟踪活动 futures 数量和协调 shutdown 的 bug ([#478])
定时器改进
tokio::timer
确实获得了一个新功能:DelayQueue
。这种类型允许用户存储值,这些值在一段时间后会被返回。这对于支持更复杂的时间相关情况非常有用。
让我们以 cache 为例。cache 的目标是为与 key 关联的值保留一段时间。时间过后,该值将被删除。一直以来都可以使用 tokio::timer::Delay
来实现这一点,但这有点挑战性。当 cache 有很多条目时,必须扫描所有条目以检查它们是否需要被删除。
使用 DelayQueue
,实现变得更加高效
#[macro_use]
extern crate futures;
extern crate tokio;
use tokio::timer::{delay_queue, DelayQueue, Error};
use futures::{Async, Poll, Stream};
use std::collections::HashMap;
use std::time::Duration;
struct Cache {
entries: HashMap<CacheKey, (Value, delay_queue::Key)>,
expirations: DelayQueue<CacheKey>,
}
const TTL_SECS: u64 = 30;
impl Cache {
fn insert(&mut self, key: CacheKey, value: Value) {
let delay = self.expirations
.insert(key.clone(), Duration::from_secs(TTL_SECS));
self.entries.insert(key, (value, delay));
}
fn get(&self, key: &CacheKey) -> Option<&Value> {
self.entries.get(key)
.map(|&(ref v, _)| v)
}
fn remove(&mut self, key: &CacheKey) {
if let Some((_, cache_key)) = self.entries.remove(key) {
self.expirations.remove(&cache_key);
}
}
fn poll_purge(&mut self) -> Poll<(), Error> {
while let Some(entry) = try_ready!(self.expirations.poll()) {
self.entries.remove(entry.get_ref());
}
Ok(Async::Ready(()))
}
}
许多其他小的改进
除了上面列出的内容之外,Tokio 在大多数 crates 中还获得了许多小的改进和错误修复。这些都是由我们出色的社区提供的。我希望随着时间的推移,越来越多的人将加入构建 Tokio 的行列,并帮助它继续发展。
因此,非常感谢迄今为止所有为 Tokio 做出贡献的人。