【译文】Rust 2024 展望:Async Rust
每年到了这个时候,人们的思绪就会转向……当然是 “Rust”。我想每年都是这样。今年对于 Rust 来说是非常重要的一年,不过我认为发生的很多事情更像是在 “为 2024 年的成功做准备”。让我们来谈谈 2024 年!我将发表一系列博文,介绍我对 Rust 感到兴奋的不同方面,以及我认为我们应该做的事情。为了把事情具体化,我将用提议目标(基本上就是我认为我们今年可以完成的一项具体工作)来构架 2024。在第一篇文章中,我将重点讨论async Rust。
我们在 2023 年做了什么
12 月 28 日,随着 Rust 1.75.0 的发布,我们稳定了 traits 中的 async fn 和 impl trait。这是一件大事。自 2019 年以来,traits 中的 async fn 就一直被 “认为是硬核“,而它们基本上是我们需要做的一切让 async 变得更好的基础。
对我来说,Async Rust 展示了 Rust 的优点和缺点。它实现了 Rust 关于 “高层代码、底层性能 “的承诺。基于经过高度调整的 Tokio 运行时,Rust 中的network service始终具有更紧凑的尾部延迟和更低的内存使用率,这意味着你可以用更少的资源为更多的客户端提供服务。此外,由于 Rust 没有对运行时进行硬编码,因此您可以编写异步 Rust 代码,用于甚至没有底层操作系统的嵌入式环境,或介于两者之间的任何地方。
然而,用与我交谈过的一位亚马逊工程师的话来说,”Async Rust 就是 Rust on hard mode”,这仍然是事实。要真正缩小这一差距,需要在语言、标准库和生态系统方面下功夫。我们不可能在 2024 年实现所有目标,但我认为我们可以取得长足进步。
目标:在第二季度解决send bound问题
去年,我们在traits 中的异步函数方面取得了很大进展,但我们仍然无法覆盖通用traits 的用例,这些traits 既可以与work-stealing执行器一起使用,也可以不与work-stealing执行器一起使用。一个非常具体的例子就是 Service
trait from tower
。要处理这种用例,我们需要解决 send bound problem。我们对这个问题有很多想法,甚至已经有了返回类型符号(子集)的原型实现,所以我们已经做好了成功的准备。我认为我们应该争取在第二季度末(基本上是夏天)完成这项工作。这反过来又会解锁 tower crate 的 1.0 版本,让我们拥有一个中间件稳定的trait。
目标:在第三季度稳定异步闭包的 MVP
异步的圣杯是,你应该能够轻松地将任何同步函数变成异步函数。2019 MVP 仅支持顶层函数和固有方法。现在,我们将其扩展到了trait 方法。2024 年,我们将迈出下一步,支持异步闭包。这将允许人们定义迭代器 map 等组合方法,并避免目前所需的复杂变通方法。
对于第一个目标,我认为我们应该努力开发 MVP。最近,Ers 和我勾画了一个我们认为非常可行的 MVP。一开始,我们创建了 AsyncFn trait ,其外观与 Fn trait 层次结构如出一辙…
trait AsyncFnOnce<A> {
type Output;
async fn call_once(self, args: A) -> Self::Output;
}
trait AsyncFnMut<A>: AsyncFnOnce<A> {
async fn call_mut(&mut self, args: A) -> Self::Output;
}
trait AsyncFn<A>: AsyncFnMut<A> {
async fn call(self, args: A) -> Self::Output;
}
…和编写 async || <expr> 等异步闭包的能力,以及一个桥梁使任何返回 future 的函数也能实现适当的 AsyncFn traits。Async clsoures 将阻止我们创建组合特质,就像一个真正漂亮的 async iterators 版本。
本 MVP 并不打算作为最终状态,但打算与我们最终采用的任何最终状态兼容。如何将 AsyncFn traits与常规 Fn traits整合起来,仍然是一个非常有趣的问题。尽管如此,我认为我们可以在探索这个问题的同时稳定上述 MVP。
目标:在第四季度为 “maybe async “编写一个 RFC(或者决定不编写!)。
围绕 async 的一个大问题是,我们是否应该支持以某种方式编写 “maybe async “代码。这个想法经历了很多名字。Yosh 和 Oli 最初发起了一种名为 “关键字泛型”(keyword generics)的东西,后来又改名为 “效果泛型”(effect generics)。我更喜欢 “trait 转换器”(trait transformers)这一框架,我还写过一篇博文,介绍trait 转换器如何让异步闭包变得更加合适。
有人对这是否是一个好的方向持怀疑态度。关于异步闭包,还有其他思考方式(不过 Errs 指出了一个问题,我希望能在以后的文章中讨论)。Boats 写了很多博文表达担忧,而类型团队的成员也表达了对编写泛型效果代码的担忧。我认为这些担忧很有道理!
总的来说,我仍然相信,像trait 转换器这样的东西可以让 Rust 感觉更简单,并帮助我们扩展以适应未来的需求。但我认为我们必须证明自己的观点!我在 2024 年的目标正是如此。我的想法是撰写一份 RFC,提出一个 “maybe async”的方案,并让 RFC 被接受。为了消除类型团队的顾虑,我认为需要将 “maybe async “正式建模为 a-mir-formality 的一部分,以便每个人都能理解它将如何工作。
另一种可能的结果是,我们选择放弃这个想法。也许复杂性真的不可行。或者是语言设计感觉不合适。我对此也没有意见,但无论如何,我认为我们都需要在今年确定一个计划。
扩展目标:稳定生成器语法
作为一个扩展目标,如果能支持生成器表达式(基本上是一种编写异步iterators的方法),那将会非常酷。Errs 最近开启了一项 PR,为异步添加nightly支持,而 RFC #3513 则建议为 Rust 2024 保留 gen 关键字。不过,要真正稳定生成器,我们还需要回答一些有趣的问题,即如何为异步iteration trait 进行最佳设计。多亏了 trait 中 async fn 的稳定化,我们现在可以进行这样的交流–而且我们确实一直在进行这样的交流!在过去的一个多月里,我们还就最佳设置进行了许多有趣的来回讨论。我还在消化所有的帖子,希望能在这个月提出一些想法(不保证)。无论如何,我认为我们有可能在 2024 年看到 async genreators 的出现,这将是一件好事,因为这将消除人们与 Pin 直接交互的主要原因。
结论:展望 2024 年
如果我们实现了上述目标,那么到 2024 年底,async Rust 将大有改进。但是,在我们真正完成所需的部分之前,仍有一些大项目需要完成。遗憾的是,我们不可能做到这一切,所以这些项目将不得不等到 2024 年之后,尽管我认为我们会继续实验和讨论它们的设计:
Async drop: 有了异步闭包之后,还有一个地方无法编写异步函数,那就是 Drop trait 。Async drop 有很多有趣的复杂问题(Sabrina 就此写了一篇很棒的博文!),但它也是用户的一大痛点。下面我们就来了解一下!
Dyn async trait:除了send bounds,,trait 中 async fn 的另一个主要限制是使用它们的 trait 尚不支持动态派发。我们绝对应该取消这一限制,但对我来说,它的优先级较低,因为现有的解决方法是使用 proc-macro 创建 DynAsyncTrait 类型。这并不理想,但它并不像send bounds,或缺乏 async closures和async drop那样是一个根本性的限制。(尽管如此,这方面的设计工作已基本完成,因此我们完全有可能在今年将其作为一项即兴工作加以实现)。
Traits for being generic over runtimes: Async Rust 能够支持 Tokio 和 Embassy 等不同的运行时,这是它的优势之一。但事实上,切换运行时或编写generic 运行时的代码非常困难,甚至不可能,这是一个关键的痛点,而运行时往往不能很好地协同工作,这就更糟糕了。我们需要为interop建立trait ,从[异步读写]开始,最终覆盖[任务生成和定时器]。
更好的APIs:当用户试图管理嵌套任务时,会出现许多最糟糕的异步 Rust Bug。现有的应用程序接口(如 FutureUnordered 和 select)有很多粗糙的边缘情况,很容易导致死锁–Tyler 曾就此发表过一篇很好的文章。我希望我们能重新审视为 Rust 程序员提供的异步 API,并建立一个功能强大、易于使用的库,帮助用户远离潜在的死锁源。理想情况下,这种 API 不会针对底层运行时,而是让用户在不同运行时之间切换,并希望能干净利落地支持嵌入式系统(也许功能有限)。我认为我们还不知道如何做到这一点,而且我认为要做到这一点,我们还需要更多的工具(如send bounds,async closure,以及很可能的 trait transformers 或 async drop)。
本文文字及图片出自 What I'd like to see for Async Rust in 2024
你也许感兴趣的:
- 【程序员搞笑图片】数据类型简明指导
- 33 种编程语言的 UUIDv7 实现
- 【外评】Rust,你错了
- 【外评】为什么人们对 Go 1.23 的迭代器设计感到愤怒?
- 华为自研编程语言“仓颉”来了!鸿蒙应用开发新语言,性能优于 Java、Go、Swift
- 【外评】JavaScript 变得很好
- 【外评】华为发布自己的编程语言 “仓颉”
- VBScript 废弃:时间表和后续步骤
- 【外评】BASIC 编程语言 60 岁了
- 【外评】为什么 ALGOL 是一种重要的编程语言?
你对本文的反应是: