19.2-异步 Rust 的现状

异步 Rust 的现状

译文 · 基于 Asynchronous Programming in Rust

异步 Rust 的现状

原文链接: https://rust-lang.github.io/async-book/01_getting_started/03_state_of_async_rust.html

异步 Rust 的部分内容享有与同步 Rust 相同的稳定性保证。其他部分仍在成熟中,会随时间变化。使用异步 Rust,你可以预期:

  • 对典型并发工作负载出色的运行时性能。
  • 更频繁地与高级语言特性(如生命周期和 pinning)打交道。
  • 一些兼容性约束,既存在于同步与异步代码之间,也存在于不同异步运行时之间。
  • 更高的维护负担,因为异步运行时和语言支持仍在持续演进。

简而言之,异步 Rust 比同步 Rust 更难使用,维护负担也可能更高,但回报是顶尖的性能。异步 Rust 的各个方面都在不断改进,这些问题的影响会随时间减弱。

语言与库支持

虽然 Rust 本身支持异步编程,但大多数异步应用依赖社区 crate 提供的功能。因此,你需要同时依赖语言特性和库支持:

  • 最基本的 trait、类型和函数(如 Future trait)由标准库提供。
  • async/await 语法由 Rust 编译器直接支持。
  • 许多工具类型、宏和函数由 futures crate 提供,可在任何异步 Rust 应用中使用。
  • 异步代码的执行、IO 和任务生成由「异步运行时」(如 Tokio 和 async-std)提供。大多数异步应用和部分异步 crate 依赖特定运行时。详见「异步生态」一节。

你在同步 Rust 中习惯的一些语言特性在异步 Rust 中尚不可用。值得注意的是,Rust 直到 1.75.0 稳定版才允许在 trait 中声明 async 函数(且对这些 trait 的动态分发仍有限制)。因此,你需要使用变通方法达到同样效果,可能更冗长。

编译与调试

在大多数情况下,异步 Rust 的编译器和运行时错误与 Rust 一贯的表现相同。但有几处值得注意的差异:

编译错误

异步 Rust 的编译错误遵循与同步 Rust 相同的高标准,但由于异步 Rust 往往依赖更复杂的语言特性(如生命周期和 pinning),你可能更频繁地遇到这类错误。

运行时错误

每当编译器遇到 async 函数,它会在底层生成状态机。异步 Rust 中的栈跟踪通常包含这些状态机的细节,以及来自运行时的函数调用。因此,解读栈跟踪可能比同步 Rust 更复杂。

新的失败模式

异步 Rust 中可能出现几种新的失败模式,例如在异步上下文中调用阻塞函数,或错误实现 Future trait。这类错误可能悄无声息地通过编译器,有时甚至通过单元测试。扎实理解底层概念(本书旨在提供)有助于避免这些陷阱。

兼容性考量

异步与同步代码不能总是自由组合。例如,你不能在同步函数中直接调用 async 函数。同步与异步代码也往往促进不同的设计模式,这使得为不同环境编写的代码难以组合。

即使异步代码也不能总是自由组合。某些 crate 依赖特定异步运行时才能工作。若有此依赖,通常会在 crate 的依赖列表中注明。

这些兼容性问题可能限制你的选择,因此请尽早调研需要哪种异步运行时以及哪些 crate。一旦选定运行时,就不必太担心兼容性问题。

性能特征

异步 Rust 的性能取决于你所用异步运行时的实现。尽管驱动异步 Rust 应用的运行时相对较新,但对大多数实际工作负载表现异常出色。

话虽如此,异步生态大多假设使用多线程运行时。这使得难以享受单线程异步应用的理论性能优势,即更便宜的同步。另一个被忽视的场景是延迟敏感任务,对驱动程序、GUI 应用等很重要。这类任务依赖运行时和/或 OS 支持才能被适当调度。你可以预期未来这些用例会有更好的库支持。

最后修改 August 23, 2026: 更新 (499855b16)