文章建议阅读时间:30分钟
作者 | 张汉东
1 前言
Rust 是一种一旦了解就会产生使用欲望的语言,Rust 语言连续八年蝉联 stackoverflow 开发者调查问卷 最受欢迎编程语言榜首就是最好的证明。
但比起“最受欢迎”的连胜纪录,增长的使用率更加值得关注。与 2022 年的调查相比,它在所有受访者中增长了 3.7 个百分点,现在紧随 Go 之后。
人们对 Rust 语言普遍的抱怨来自没有太多的 Rust 工作岗位。然而,Rust 语言已经在一些至关重要的基础领域开始铺垫。是否普遍使用不是评价一门语言的唯一标准,更好的方法是看这个工具在哪里被使用以及这个使用案例的重要性。
这也是本文的写作目标。希望大家通过这篇文章对 Rust 语言有一个全面且客观的认识。
在写本文之时,TOIBE 编程语言九月排行榜出炉,Rust 排名上升到第 17 位。
并且,Jetbrains 也宣布发布独立的 Rust IDE : RustRover。拥有独立的商业 IDE,不是说这个 IDE 最好,而是意味着 Rust 迈入主流语言行列。
总之,今年是 Rust 出圈的一年。
本次报告的所有内容都来自于互联网公开信息,如有错误或不宜在本报告中提及的内容,请及时告知。往年的 Rust 生态报告参见附录。
2 大纲
Rust 语言及其生态现状总览
Rust 语言现状:特性、优势和挑战
Rust 开源社区治理:组织结构、贡献者以及影响力
Rust 生态总览:主流库和框架
深入 Rust 应用领域
Rust 在全球商业巨头中的应用
Rust 在高科技和工业领域中的采用案例
Rust 语言实践经验漫谈
如何从成功的 Rust 项目案例中学习:项目背景、架构设计、实现亮点
Rust 与 C/Cpp 交互实践:FFI 使用和安全性
AI 时代 与 Rust 语言学习
Mojo vs Rust
让 AI 成为自己的学习助手
附录:往年的 Rust 生态报告
3 Rust 语言及其生态现状总览
要了解 Rust 语言及其生态现状,我们依然可以从 Rust 语言设计原则出发。
而 Rust 语言的设计原则本身也是不断发展变化而沉淀的。在 Rust 诞生的开端,是由 Rust 团队内部一些可以主导 Rust 语言设计的人员遵循共同的某种思想来创造 Rust 。在前 Rust 核心团队成员 Brson 在 2021 年写的 《造就 Rust 的无名英雄》 一文中透露了早期引领 Rust 设计的重要幕后人物戴夫·赫尔曼( Dave Herman)为 Rust 发布稳定版 v1.0 所做的诸多奠基性的贡献。
Rust 稳定版 v1.0 发布之后,又经历了六年的发展(2015-2021),由 Rust 语言团队作为 Leader 的 Niko 提出了更加具体和广泛的 Rust 语言原则 《Rustacean Principles 》 ,其中不仅仅包含了 Rust 语言该如何设计的原则,而且还包含了 Rust 语言开源社区成员(Rustacean)们如何更好地参与社区活动的原则。
这些原则可以概括为以下三个重要方面:
Rust 是什么?
Rust 语言是一种让每个人都能构建可靠高效软件的语言。
一个专注于创建、设计和维护该(Rust)语言及其生态系统的开源社区。
Rust 语言设计:Rust 如何为用户赋能,Rust 语言的设计是以下原则的权衡。
与支持性和生产力相矛盾。
通过以某种方式向 Rust 程序暴露所有核心系统功能,并应该使用 unsafe Rust 来避免让用户降级去使用 C 。
与支持性和生产力相矛盾,因为透明性通常需要暴露更多细节。
通过让 Rust 变得更加透明来保证透明性,努力避免那些会对全局产生成本的特性(即即便用户未用到的特性也会在运行时产生成本的特性)。
与 可靠性和性能相矛盾。
通过保证版本的稳定性和打造繁荣的生态来提升生产力。
与可靠性 和 多样性 相矛盾。
通过优化开发中体验,提供更好的工具来增强支持性。
与 支持性 和 某种情况下的生产力 相矛盾,用户可能无法从其他语言的某些习惯中获得便利。
与 透明性 和 多样性 相矛盾。许多优化依赖于事物发生的顺序和方式的透明度。
依赖于零成本抽象和只提供捕捉用户意图的适当的细节。
与 生产力和支持性相矛盾。因为可靠要依赖各种检查,这些检查会影响系统的构建难度。
与 多样性 相矛盾,因为可靠性的能力总是有限的,那么也会影响用户所能构建系统的领域范围。
依赖类型安全和使用多种机制鼓励用户不隐藏发生错误的条件来保证可靠性
可靠性(⚙️ Reliable)。如果它编译,它就可以工作。
高性能( Performant)。既高效执行又使用最少内存。
支持性( Supportive)。语言、工具和社区随时为用户提供帮助。
生产力( Productive)。让工作事半功倍,短时间内构建高质量系统。
透明性( Transparent)。让用户可以预测和控制底层细节。
多样性( Versatile)。你可以用 Rust 做任何事,从简单的脚本到复杂的系统,通用语言,多领域应用。
Rust 社区如何治理才能更贴近
Rustacean:用于帮助 Rust 核心团队和社区贡献者良好合作。善良体贴。相互尊重彼此才是构建 Rust 未来的基础。
给用户带来快乐。首要目标是让 Rust 用户更有效率和能力。希望人们喜欢使用 Rust,如果他们愿意,也喜欢参与它的社区。
畅所欲言地表达自己。带上你的专业知识,并愿意为你认为正确的事情进行辩论。
认可别人的知识。没有人能垄断好的创意。Rust 团队需要汲取优秀的建议来改进设计。
从小处开始。寻找完美的设计需要迭代。大处着眼,小处着手;当你了解更多时,不要害怕改变。
跟进。说你会做的,做你说的。
把爱传出去。Rust 项目成员需要识别有潜力的贡献者,有义务去发展新的成员,并且当好教练的角色。
信任和委托。赋予他人权力意味着愿意让他们以他们认为最好的方式做出决定。
总的来说,这些原则规范着 Rust 语言的演进方向。
那么,截止 2023 年的今天,让我们依据这些原则来再次审视 Rust 语言及其社区和生态,看看 Rust 语言有没有成为它想成为的语言。
Rust 语言现状:特性、优势和挑战
2023 年,Rust 距离 2015 年 5 月稳定版 1.0 发布已经经历了八个年头,发布了 71 个稳定语义化版本,2015、2018、2021 三个 Edition 版本。
这八年中,Rust 语言提供的特性不仅仅在内存安全上取得了成果,而且在工程架构方面也得到了很多领域实践的验证与认可。
目前,Rust 已经进入了更加成熟与扩大应用规模的阶段。
语言特性
2023 年 Rust 稳定版有哪些更新
2023 年初 Rust 语言发布了 1.67 版本,截止到今天这篇文章为止,已经发布到了 1.72 稳定版,10 月 5 号马上发布 1.73 稳定版。参考 releases.rs
Rust 语言更新改进是全方位的,包括六个主要方面:语言、编译器、库(core/std)、稳定 API ,Rustdoc、Cargo 、兼容性变化以及不影响稳定接口的内部改进。
我们可以按 Rust 设计原则来对这些更新进行归类,当然,这里不会把每一条更新都列出来,但会归纳一个整体趋势。
可靠性提升
允许在所有
repr(Int)枚举类型上指定明确的判别标准允许仅在生命周期上有所不同的相同类型之间进行转换
如果
impl Trait有 super trait 有#[must_use]则触发must_uselint将
Sized谓词定义为共归的(Coinductive,或称反向归纳),允许循环稳定
efiapi(用于定义兼容 UEFI 接口的函数)调用约定启用 s390x-linux 的 Sanitizers
为了确保 BinaryHeap 的不变量(Invariant),对
peek_mut()进行泄漏放大(Leak Amplification)处理(这个 Leak amplificatioin 是一种非常巧妙的策略,深入了解这个 PR 你会受到新的洗礼)对于未对齐的对齐字段的引用现在将成为一个严格的错误
在指针解引用处插入对齐检查作为调试断言。这样可以在运行时捕获未定义的行为
在编译时常量求值期间始终检查对齐
Cargo 在通过 SSH 克隆索引和依赖时没有执行 SSH 主机密钥验证。攻击者可以利用此漏洞进行中间人攻击。此漏洞已被分配 CVE-2022-46176。所有在 1.66.1 版本之前的 Rust 版本中,包含 Cargo 的都存在漏洞,升级到 1.66.1 以后的版本则无问题)
高性能
启用 LLVM 编译的 BOLT 功能
基于数据流分析添加新的 MIR 常量传播
为
Vec -> VecDeque添加 O(1) 的转换保证Const 上下文稳定了
VecDeque::new
支持性
升级至 Unicode 15
将 libstd 的 libc 更新到 0.2.135
在文档中添加 Rustdoc 警告,用于无效的 HTML 标签生产力
允许在模式中使用
..=X添加
cargo remove以删除 Cargo.toml 中的依赖项放宽对
asm!操作数的顺序规定
透明性
NonZeroXxx 布局保证
添加关于
Cell的内存布局的文档PhantomData 布局保证
多样性
添加
armv5te-none-eabi和thumbv5te-none-eabi作为 Tier 3 目标增加对链接 macOS 通用库的支持
不在
wasm32-wasi上导出__heap_base和__data_end只在
wasm32-unknown-unknown上导出__tls_*为除
C或cdecl(已经支持)之外的调用约定启用可变参数支持为索尼 PlayStation 1 添加 Tire 3 目标
提升
{aarch64,i686,x86_64}-unknown-uefi为 Tier 2 目标为 QNX Neutrino RTOS 增加 Tier 3
no_stdAArch64/x86_64支持将
powerpc64-ibm-aix添加为 Tier 3 目标稳定
raw-dylib,link_ordinal,import_name_type和-Cdlltool将
aarch64-apple-darwin的目标 CPU 设置为apple-m1将
loongarch64-unknown-linux-gnu提升至 Tier 2 目标
从上面罗列的一些语言改进特性中,可以简单地概括 Rust 语言稳定版在 2023 年的演进趋势:
持续提升 Rust 语言的可靠性和安全性
持续提升 Rust 语言在多样化领域的支持,比如对 Windows、WebAssembly、Linux、Android、索尼 ps,还有 loongarch64 都有支持。另外,其实也添加了 OpenHarmony
*-unknown-linux-ohos为 Tier 3 目标。稳定了很多 API 对于提升生产力和降低 Rust 学习曲线是很有帮助的。
目前正在进行中的语言级重大改进
Rust 2023 的发展目标是为 2024 Edition 服务的,让 Rust 更加成熟并且让 Rust 应用的规模更加扩大,即,让 Rust 遍布四海。
除了今年稳定版已经发布的那些特性之外,Rust 语言还有一些重大的改进正在进行中。
异步编程向真正的零成本抽象迈进。让 Rust 异步编程遍布四海,那么在高性能、生产力和多样性上面更加重要。目前异步编程已经在生产环境基本可用,但是在零成本抽象的目标上还差很多工作,具体可以查看 wg-async roadmap 。其中马上要稳定的特性是 TAIT(Type Alias Impl Trait) 。该特性允许为
impl Trait创建类型别名,impl Trait是静态分发,这样就可以在 trait 关联类型(ATPIT, Associated type position in traits)中使用impl Trait,尤其可以改进现在异步编程模型,有利于即将在 1.74 版本中稳定async fn in traits的 MVP (最小化可用)功能。
Rust 团队在评判这个功能 MVP 标准的时候也是结合了实际生产中的典型案例进行改进,包括 AWS SDK 、 开源框架 tower 、嵌入式异步运行时 embassy 以及 Fuchsia OS 网络栈、微软内部工具等实际使用案例的各种情况来确定 async trait 到底该如何设计。
泛型关联类型(GAT)的持续完善。GAT 自从在去年(2022.10)稳定了 MVP 版本以后,极大地提升了 Rust 语言的抽象表达能力,帮助众多知名开源项目在维持零成本抽象的基础上简化了抽象架构。但是还有 很多未解决的问题,比如如何保证 GAT 的向后兼容性,如何让 GAT 更易于使用等等。
为 Unsafe Rust 定义规则。在 Rust 语言发布的最初,Unsafe Rust 使用起来好像很简单,但是随着 Rust 的发展,Unsafe Rust 变得越来越复杂,官方需要明确一些规则,为开发者及丝滑的安全检测工具提供方便。一些正在进行的工作包括:
指针溯源(Strict Provenance),目前已经实现了 Strict Provenance MVP。由
[feature(strict_provenance)]特性门开启。这个安全规则让 Rust 具有极其严格的指针来源要求。也就是说,如果开发者想将某个东西视为真正的指针,可以进行偏移(Offset)和解引用操作,那么从该指针到开发者尝试访问的原始分配之间必须有一个不间断的监管链。如果开发者在中途将指针转换为了地址,则无法再从地址转换为指针(地址和指针转换滥用是 C 语言中安全 Bug 的温床)。这个安全规则的落地,会让 Rust 指针使用更加安全,目前还未进入 FCP。为了更加准确地定义 Unsafe Rust 的操作语义,官方成员 Ralfj 发起了 MiniRust 项目,该项目用于定义 Rust 语义规范,为 MIR(Rust 语言中级中间语言)提供基石,也可以为 Miri 或 Kani 这样的检测工具提供语义基础。由此也创建了由 Ranfj 领导的 操作语义团队(opsem Team)。
稳定 MIR API。像 Miri 和 Kani 这样的工具属于动态验证工具,但是它有受限范围,比如无法对 FFI 进行验证。所以需要提供静态验证的工具,那么由官方来提供稳定的 MIR API 就成了需求。所以官方开辟了 stable mir 项目,目前积极更新的是 Rust 编译器内部的 rustc_smir crate。
Rustc Trait System 重构计划。今年 Rust 官方成立了 类型团队,专门来处理 Rust 语言团队委托的类型系统设计和实现的相关工作。因为 Rust 语言类型系统是重中之重,而 Rust 语言类型系统一直有技术债需要处理,所以专门成立这个内部团队。主要的工作会涵盖 下一代借用检查器 Polonius 的设计与实现(目前已经引入 Nightly ,但是因为性能问题没有面向大众稳定),以及 trait 系统重构(chalk 虽然实现了有几年,但它不是 Rust 的长期解决方案,但目前仍保留其实验目的) 等。目前 trait 系统重构的优先级更高。同时,类型团队也有形式化定义类型系统的职责,以此推动 Rust 语言规范的落地。目前 a-mir-formality 是 Rust 类型团队开始进行的类型系统形式化工作。上面介绍的 GAT/TAIT 等特性也是由类型团队来推动。类型团队计划在 2027 年底建立一个能够满足 Rust 语言所需新功能的可靠、可测试和有文档支持的类型系统平台。但这个目标也是分阶段的,在今年年底的目标是将重构的新的 trait 系统求解器替换掉旧的,并且将
a-mir-formality形式化类型系统融入到语言设计过程中。(这是否意味着 Rust 语言将从一个最初由工程实践驱动的语言走向学院派?我的期望是它可以平衡实践与学术,目前看是这样的)。目前新的 trait 求解器已经可以通过使用 rustc 标志-Ztrait-solver=next在 Nightly 上使用。
Rust 编译后端 GCC 的支持。目前 Rust 官方正在进行一个 Rust 后端 GCC 支持
rustc_codegen_gcc。另外一个由 GCC 社区发起的 GCC Rust 前端 Rust-GCC 项目,Rust-GCC 的动机包括推动 Rust 的采用,复用现有的 GCC 改进,以及为更多的系统提供后端支持。项目的当前状态包括处理 const generics(常量泛型)、intrinsics(内置函数)、borrow-checking(借用检查),以及针对旧版本的 libcore 进行定位。Rust-GCC 在 2022 年共有超过 50 位贡献者,包括多名学生、实习生、GCC 开发者以及 Rust 核心团队成员。Rust-GCC 的详细进展可以参考 GCC Rust 前端 2023 报告 pdf。Rust 基金会安全计划。随着 Rust 语言的流行度不断攀升,其优点在开源生态系统的各个角落以及更广泛的领域都得到了越来越多的认可。就像开发人员越来越多地转向 Rust 来构建高性能的系统一样,一些重要的政府机构也开始将 Rust 视为更安全的编码解决方案,特别是用于改善软件供应链的安全性。Rust 作为一种内存安全和高性能的语言的卓越声誉,以及其可见度、流行度和采用率,每天都在增长。然而,为了适当地支持 Rust 的未来和其不断增长的社区,并确保 Rust 继续履行其安全和安全的承诺,Rust Foundation 认为必须采取积极的措施来加强和扩大生态系统中的安全性。这就是为什么他们在 2022 年 9 月启动了安全倡议,得到了 OpenSSF 的 Alpha-Omega 项目和 Rust Foundation 铂金会员 AWS 的慷慨支持,以及新加入的铂金会员 JFrog 的技术支持,Wiz 的基础设施支持,以及铂金会员 Google 的咨询。在 2022 年 12 月至 2023 年 7 月期间,Rust Foundation 安全倡议的工作主要集中在以下几个优先领域:
雇佣 Rust Foundation 安全工程专家:Rust Foundation 已经聘请了全职的软件安全专家,他们正在与 Rust 项目的领导层合作,确定初始的安全优先事项,开始对项目和社区进行全面的审计,并开始设计实际的解决方案。
对 Rust 生态系统进行安全审计:Rust Foundation 和 crates.io 团队正在合作,以提供更深入的 crate 安全洞察,并更突出地展示 crate 安全信息。他们的工作目前集中在软件供应链安全上。评估工作包括泄露的秘密、恶意 crate 检测和安全最佳实践评分模型。
对 Rust 生态系统进行威胁建模:威胁建模练习使 Rust Foundation 和 Rust 项目能够更好地理解安全审计识别的风险。在开发以下四种威胁模型时,基金会已经与 Rust 项目的 crates.io 团队、基础设施团队、安全响应工作组以及安全代码工作组进行了咨询,此外还咨询了特定的外部利益相关者。我们期待尽快分享所有威胁模型的详细信息。
在 Rust 生态系统中倡导安全实践:Rust Foundation 团队已经编写了一份 RFC ,以便在满足一系列安全阈值后隔离问题 crate。如果获得批准,这个功能将使得在公开使用 crate 时,可以在 crates.io 基础设施内进行安全检查以确保其安全性。此外,Rust Foundation 团队已经开始与基础设施团队接触,开始记录 Rust 项目中的访问控制配置和取消配置的过程。
基于研究开发工具、特性和建议:Rust Foundation 安全工程师 Walter Pearce 创建了一种名为 Painter 的工具,该工具旨在解决使用其他工具(如 Cargo Audit)时的问题,并确定风险。此外,Rust Foundation 和 crates.io 团队在 2023 年 6 月合作发布了一份声明,阐述了如果任何一方收到法律约束的数据请求,我们共同的一般处理方式。
开发文档以揭示 Rust 生态系统中的安全性:通过在技术 Rust 文档中概述安全风险、漏洞和考虑因素,开发人员将更好地遵守安全最佳实践,并在部署 Rust 代码时做出明智的选择。Rust 的高质量安全文档的扩展将使开发人员能够在 Rust 开发过程的早期阶段识别并解决潜在的漏洞,防止常见的安全陷阱,并更好地教育社区关于 Rust 现有的安全优势。
解决通过研究识别的 Rust 安全问题:尽管初始的 Rust 安全审计尚未完成,但我们负责研究 Rust 安全状况的工程师已经识别并优先解决了几个安全问题。在 Rust 生态系统中,我们将通过适当的渠道报告更多的安全问题,包括在必要时通过 Rust 项目安全响应工作组。
语言规范
Rust 没有语言规范这件事,这几年一直是某些 Rust 反对者口中的“弊病”之一。从 2023 年开始,这个情况应该会得到改善。
首先,由 Ferrous Systems 公司联合 AdaCore 共同创建的 Ferrocene 语言规范(FLS) 已经正式发布。该规范主要用于 Ferrous Systems 和 Adacore 合作的项目 Ferrocene,旨在将经过验证的 Rust 工具链引入安全关键环境。FLS 主要是为了以标准化的形式记录 rustc 编译器的当前行为,以便进行资格认证。如果 FLS 与编译器行为不一致,规范将会更新。截止目前, Ferrocene 正在进行 ISO 26262 和 IEC 61508 安全认证,预计十月份发布。未来还会进行更多安全认证。
小知识:ISO 26262 标准定义了四种汽车功能安全(Function Safety)完整性等级 (ASIL) A,B,C 和 D,其中 'D' 代表最严格等级。而 IEC 61508 (代表工业自动化)则规范了电机电子的相关软、硬件及系统的安全强度, SIL 3 为单个产品的最高等级。除此之外,还有核工业、航天、石化、电网、医疗软件等各种安全认证标准。
除此之外,Rust 语言官方团队也正式接受了 《Rust Specification》的 RFC#3355。意味着,Rust 语言官方团队正准确起草 Rust 语言规范,目前 Rust 基金会和 Rust 领导委员会已经批准这一计划,准备招聘专业的撰稿人来全职起草这份官方的 《Rust 语言规范》,并且也打算让这个撰稿人能成为语言规范开发过程中的领导者。该规范的进展参见#113527。
在这里值得声明的是,Rust 官方团队并不希望用户被《Rust 语言规范》这个名称误导为它就是 Rust 语言的权威的标准。这也是官方没有将其命名为《Rust 语言标准》的原因。《Rust 语言规范》只是对 Rust 语言最终完整性和准确性的承诺。另外官方团队还将在正式发布之前考虑“规范”一词可能带来的“法律影响”。Ferrocene 团队的 Leader 也声称,任何编译器的需求文档,无论什么形式,都会被称为“规范”,所以 Ferrocene 语言规范也采用了“规范”而非“标准”,尽管 Ferrocene 需要安全认证。
关于 Rust 语言自身是否需要一个 Rust 标准,库团队 Leader Mara 专门写过一篇文章论证过这个问题。该文章提到 C 和 Cpp 标准由各自的 ISO 委员会制定,其中 C 标准超过 500 页,Cpp 标准近 2000 页。遵循这些标准,很多公司研发了自己的编译器,公司投资参与标准化委员会的一个原因是能够影响语言发展的方向,尽管这可能会相当昂贵。
但是 Rust 语言是现代语言,它诞生在一个开源协作和跨平台软件相当普遍的年代,这种情况与 40 年前 C/Cpp 诞生的年代大有不同。Rust 语言,只有一个并且在未来也会保持唯一的官方编译器。而 Rust 基金会拥有 Rust 语言的商标。如果需要一份 Rust 语言标准来定义 Rust 编译器,那么也不应该是 C/Cpp 标准委员会那种形式。
Rust 语言作为一个开源的项目,它演进的方式是非常现代化的。Rust 语言每六周发布一个稳定版的编译器,意味着,每六周就会改变一次 Rust 编译器的“含义”。如果要对 Rust 语言进行大规模更改或添加新的特性,则需要通过 RFC 流程来完成,这些文档都需要公开评审。一旦有官方权威成员认为提案达到可接受状态,并且最多两名非权威成员确认之后,就会进入为期 10 天的最终评审期(FCP)。一旦 FCP 完成并且 RFC 合并到 RFC 存储库中,该文档将在 RFC 书中提供,并在 GitHub 上开启一个跟踪问题以追踪新功能或变更的开发进展。
然而,新功能也不一定保证会出现在未来的稳定版本的 Rust 中。一旦该功能完全实施,所有未解决的问题都得到解决,关于未来也不再有持续的讨论,权威团队的成员可以提出稳定化 FCP。一旦一个特性稳定了,就不能移除它。Rust 语言对稳定性有严格的要求,非常注重向后兼容性。官方通过 crater 工具来检测 Rust 编译器发布过程中可能出现的回归问题。
除了语义化版本之外,Rust 语言还提供版次( Edition )。这是为了允许 Rust 语言能以不兼容的方式进行一次改变。比如之前添加 async/await 关键字,为了不破坏生态系统中一些 crate 中以这两个词命名的代码,就以 Edition 来发布。类似于 Cpp 98 / Cpp11/ Cpp 20 ,但 Rust Editions 可以混合使用,并且可以根据 crate 进行选择。例如使用 Rust 2018 Edition 编写的代码可以很好地使用 Rust 2015 Edition 和 Rust 2021 Edition 编写的依赖项。
Rust 在这样的演进之下,拥有一个帮助保证维护 Rust 稳定性的语言规范,其实也是非常有必要的。前面提到的 Ferrocene 语言规范团队也非常希望 Rust 官方团队以 FLS 为起点来构建 Rust 官方的语言规范。但问题是,Rust 语言是否需要一个标准?即类似于那些 ISO 或 ECMA 标准化机构所做的工作。但是对于像 Rust 语言这样演进的一门语言来说,将责任移交给一个标准组织意味着放弃官方团队的控制权,这几乎没有任何好处,官方团队将失去塑造他们认为最好的流程的能力,也许再也无法保证一个符合开源社区标准的开放和包容的环境。
许多公司和个人参与 C++ 标准化以影响该语言,以向该语言添加自己的特性。然而,对 Rust 规范的努力并不是为了改变 Rust。对于 Rust 来说,标准化的目的是:
拥有标准和准确定义的语言特性规格说明文件。
一个开放的语言演变过程。
保证稳定性。对于
2和3来说,Rust 其实已经做到了,现在缺乏的就是1。Rust 语言规范就是填补这个空白。
Rust 开源社区治理:组织结构、贡献者以及影响力
Rust 语言自诞生以来,就把开源社区作为语言的一部分。Rust 语言社区一直都是开源社区的典范与榜样。任何事物的发展过程都不是一帆风顺的,Rust 语言开源社区也是一样的,需要在不断的犯错和修正的循环中成熟。
2023 年 Rust 开源社区出现了两件不得不说的大事。第一个是 Rust 基金会修改 Rust 商标政策,另一个是 RustConf 主题演讲作者被降级的事件。这两件事在社区中产生了很大的影响,所以这是不得不说的事情。让我们简单回顾一下这两件事。
Rust 基金会修改 Rust 商标政策
Rust Foundation 在今年提出了一项关于 Rust 商标政策的修改建议,这引发了社区的广泛关注和讨论。这项修改建议主要涉及对“Rust”这个词和其 Logo 的使用规定,包括建议人们在他们的 Rust crate 名称中不要使用“Rust”,例如,建议使用vulture-rs而不是vulture-rust。这些草案的变动引发了社区的反弹。
在咨询期间,Rust 社区的许多人对政策草案及其监管团体提出了问题、关注和困惑。Rust Foundation 在声明中表示,他们理解制定 Rust 商标政策的过程应该更加透明,并为此道歉。社区的反应甚至导致了一部分人以“Crab”(螃蟹)的名义对 Rust 语言进行了分支(crablang),以抗议预期的对侵犯组织的 Rust 和 Cargo 商标使用的打压。(这个 crablang 分支仅仅是为了表达抗议,结果被国内很多技术媒体解读为 Rust 语言分叉。真正想分叉 Rust 语言,不仅仅需要技术人才,还需要大量资金才做得到,而不是仅仅在 GitHub 上 fork Rust 开源仓库)。
之后,Rust Foundation 试图通过一份声明来缓解这场争议,他们承认草案并不完美,并表示他们承诺修正任何被指出的错误,并考虑我们收到的反馈。他们还注意到,他们看到了“针对基金会员工的大量骚扰和滥用”,并表示他们将执行 Rust 项目的行为准则以保护这些人。
Rust 的创造者 Graydon Hoare 在 Reddit 的一个讨论线程中对社区的反对意见表示了支持。他写道,新的政策让所有人都停止使用名字和 Logo,这是社区成员多年来一直在做的事情,而旧的政策是允许他们这样做的。
Rust Foundation 在之后声明中表示,他们将考虑社区的反馈,以制定进一步的草案。他们表示,政策制定过程的咨询阶段旨在给 Rust 社区成员提供一个机会,让他们能够审查商标政策的初稿,并表达他们的问题、关注和评论。这个过程帮助他们理解,初稿显然需要改进。在下一阶段,他们将提供更多的进展更新,并努力解决被提出的问题。虽然他们对反馈的审查刚刚开始,但已经很明显,对初稿的许多批评是有效的,他们将在政策的下一个版本中解决这些批评。
这件事引发争议的可能原因是,大家对新商标法的理解产生了混淆,这一点 Rust 语言库团队 leader mara 给出了解释: 发布有关 Rust 的内容是可以的,但是一家公司不能未经许可就称某物为“Rust 语言规范”。
社区有人打趣:简而言之,这是关于 Rust 商标所有权的问题,允许引用,但必须通过借检查器。
当然,Rust 基金会的出发点是好的,但需要在社区和法律之间寻找一个平衡点。期待一个合理的商标政策。
Keynote 演讲降级事件
事件背景:
ThePhD 是一个知名的 Rust 社区成员,他被邀请在 2023 年的 RustConf Keynote 上发表演讲。然而,他的演讲在会议开始前的最后一刻被降级为一个普通的会议议程。
引发争议 的原因:
ThePhD 一直在为一项实验性语言功能(Rust 语言编译期反射)制定提案,这项工作得到了 Rust 基金会的赞助。
今年,他的工作引起了 RustConf 组织者的注意,他们邀请了作者在 2023 年的 RustConf 上发表主题(Keynote)演讲,显然是由"Rust 项目领导层" 投票选出的。
作者选择将上述提出的语言特性作为他们演讲的主题,并向 RustConf 的组织者多次声明了他的工作还没有 RFC/Pre-RFC ,可能会让听众产生误会,以为 Rust 语言团队要支持编译期反射了。但是 Rust 项目领导都明确表示可以作为主题演讲。
在此之后的某个时间点,RustConf 的组织者联系了作者,告知他们的演讲从主题演讲降级为普通演讲,显然是在 Rust 项目领导层的要求下进行的。他们不希望给人们留下实验性提案(甚至还没有成为预备 RFC 的阶段)是语言官方方向的印象,并且显然担心将其作为主题演讲会给人们留下这样的印象。
结果,作者(ThePhd)完全退出了 RustConf 演讲。
事件影响:
这个决定引发了 Rust 社区的广泛讨论。
首先,作为邀请 ThePhd 作为主题演讲的 RustConf 组织人员 JT 发文宣布 《为什么我离开 Rust 》。因为他认为这是 Rust 组织对领域专家的一次羞辱,让他感到极度不适。他 感受到 JeanHeyd (ThePhd)被羞辱时的痛苦和失望,心碎了。最关键的是, ThePhd 是一名黑人,这种先给予尊重然后再剥夺的降级对他而言是非常敏感的。(需要说明的是 JT 只是退出 RustConf 相关组织)
很多人可能难以理解 Keynote 主题演讲在美国的重要性。作为 Keynote 演讲除了是一份荣誉之外,还对找到一份非常不错的工作提供了极佳的机会。但是 ThePhd 的生气应该不是因为失去这种职业机会,他本身就是非常优秀的 C 语言工程师。他生气是因为自己没有得到应有的尊重,被 Rust 组织中某个人利用自己的职权之便,对他的 Keynote 演讲资格进行了「私人审判」。因为降级的过程并没有得到全体领导层投票,只是某人的一个私人决定,所以他的质疑是合理的,这可能是因为歧视黑人或者是 Rust 官方团队对他的主题内容相关工作不认可但没有明确传递给他。
一个类比。他们说:“嘿,thePHD,你在我们的新电影中得到了主演角色... 哦,实际上... 开玩笑的,你是那个呆萌的配角。”
此事经过激烈的社区讨论之后,库团队 Leader mara 再次就 ThePhd 这件事发布声明,她提到了事情的真相:在领导层决策过程中,他们没有做到检查和确认这些主题演讲的责任,而错误传递 ThePhd 是主题演讲的信息,等日程表最终确定以后,ThePhd 被私下告知了这个变动,当然无法接受。
后续行动:
Rust 官方发文对 ThePhd 主题演讲降级事件进行了公开道歉,并且承认事件的主要原因是领导对话的决策和沟通过程有问题,这是组织和流程上的失败。
为了改进开源社区治理,避免此类问题再次发生,官方宣布成立 Rust 领导委员会(Leadership Council) ,这是 Rust 项目的顶级治理机构,由 RFC 3392 发起提案。该领导委员会将负责最高级别的治理问题,而 Rust 项目的大部分责任(如编译器和核心工具的维护、语言和标准库的演进、基础设施的管理等)仍由九个高级团队承担。
事件总结
有人说,这些事件对于 Rust 组织来说是一个有趣的“成长”时期。我很认同这个看法。Rust 语言开源社区的发展并没有一个成熟的前车之鉴或榜样可以借鉴,只能在犯错中成长,良好的开源社区治理不会偶然发生。
但我们也不能忽略每次犯错所付出的代价。
ThePhd 在经历此事之后,完全终止了他对于 Rust 编译期反射的工作。这是非常令人失望的。如果你看过 ThePhd 对于编译期反射的工作报告,你会认可他工作对 Rust 语言的价值。这是 Rust 语言的损失。我不知道 Rust 官方如何弥补这个损失。
也许未来 Rust 的某个版本会支持编译期反射,但这次事件无疑让这个非常有价值的语言特性延后了。
哪里有人类,哪里就有政治。
由于 Rust 没有明确的“所有者”,而是以更加开源、分散和公开的方式进行开发,这些失误非常明显(当然,这也有助于人们试图更好地构建“社区”的普遍态度)。所以,Rust 具有更复杂的社会性,可能会引发更多冲突。这也是成立 Rust 领导委员会的必要性。
You don't have to be perfect. These are the values which we think make the Rust community better. But it doesn't mean that you need to make the community better in every possible way, your personal happiness is more important. If you feel that some of these values don't align perfectly with the way you prefer to work, that's fine, as long as you follow the code of conduct.
Rust 社区的 Matklad 说的非常好:“你不必完美。这些是我们认为能够让 Rust 社区变得更好的价值观。但这并不意味着你需要在各个方面都让社区变得更好,你个人的幸福更重要。如果你觉得其中一些价值观与你偏好的工作方式不完全一致,那也没关系,只要你遵守行为准则即可”。
但现在看来,不仅仅是遵守行为准则这么简单就能治理好开源社区。
作为 Rust 开源社区的普通一员,我只能祝愿 Rust 语言和社区能顺利发展下去。
【快速解读】ThePHD :Rust 编译期反射
社区的人们总喜欢关注八卦,有几个人正在关心 ThePhd 这项工作的内容呢?
ThePHD 研究的 Rust 编译期反射对 Rust 语言非常有价值。这里做一个简单的解读,以后有时间再深入。当然目前该工作应该已经停滞,并且也从来未曾得到 Rust 项目官方团队的认可,因为还没有机会去发 pre-RFC 讨论。
这篇文章主要探讨了在 Rust 中实现编译时反射的可能性。作者首先说明 Rust 目前并没有真正的编译时反射功能, 常见的像 rocket.rs 这样的宏只是利用了 proc macro 在预处理阶段生成代码的手段,而 proc macro 完全依赖于第三方库 syn 。
目前社区里依赖Anytrait 实现的运行时内省功能(比如 bevy_reflect),则不是零成本抽象的。
作者认为 Rust 当前的 trait 系统有以下局限:
孤儿规则(Orphan Rule)限制了外部 crate 类型的 trait 实现,导致需要大量 wrapper 和特殊类型来实现一些通用功能
trait 无法表达对字段的完整约束, 无法进行编译时遍历和计算
缺少变长参数功能, 无法处理异构(heterogenous)集合
元组访问需要硬编码索引,无法进行编译时编程
使用 访问者(visitor)模式进行遍历也需要维护状态,导致代码不优雅
为此, 作者提出在引入语言级编译期内省的功能( 通过在std::introwospect和core::introwospect模块 API )来试图解决这些问题:
introwospect_type: 反射类型信息introwospect: 反射调用 visitorintrowospect_over: 遍历调用 visitor
但是这些关键字都需要编译器的支持, 在当前版本的 Rust 中无法实现。
作者认为 Rust 的 trait 系统在表达编译时反射方面还有不足, 需要 const 泛型表达式等功能的加强。他们计划继续探索这一方向, 为 Rust 提供更优雅的编译时反射功能。
总的来说, 文章深入探讨了 Rust 的泛型编程现状, 分析了实现编译时反射的需求和潜在问题, 为 Rust 的类型系统提供了很好的反馈和建议。
好可惜,希望后续有人能接手这份工作,当然希望 ThePhd 可以继续完成它。
Rust 生态总览:主流开源库和框架
截止 2023 年 8 月,crates.io 上面 crates 下载量为 400 多亿次,一共有超过 12 万(121,520)个 crates。
crates.io 巨大的下载流量也是 Rust 官方一个巨大的负担,为了改进这个状况, Rust 官方现在修改新索引协议,从 Rust 1.68 版本开始提供。新的索引协议为“稀疏(sparse)”协议在访问 crates.io 时通常会显著提高性能。新协议不再使用 git,而是直接通过 HTTPS 从索引中获取文件。Cargo 只会下载与开发者项目中特定包依赖相关的信息。
以下会罗列一些较为知名的库和框架,仅供参考。Rust 生态目前非常丰富,没有罗列出来的不等于它就不知名不常用。
基础库与开发工具
rust-analyzer,无疑是大家最喜爱且 Rust 开发必备的工具。跟它竞争的工具有:
intellij-rust ,用于 Intellij
rust.vim,用于配制 Vim
rust-mode,用于配置 Emacs
Clippy,用于提升你代码质量的必备工具。配套工具 rustfmt。
PyO3,流行的 Python 解释器的 Rust 绑定库,Rust 在人工智能领域开疆破土必备工具。
neon,流行的方便编写安全的 Node.js 模块的 Rust 绑定库。
Rustler,流行的方便编写安全 Erlang NLF 函数的 Rust 绑定库。
cbindgen,流行的自动为 Rust 代码创建 C 绑定的库。
cxx,用于从 Rust 安全调用 C++ 代码,以及从 C++ 安全调用 Rust 代码,不受使用 bindgen 或 cbindgen 生成 unsafe 的 C 风格绑定时可能出现的许多问题的影响。
rust-bindgen,流行的为 C(部分 Cpp)库自动创建 Rust 绑定的库。
tarpaulin,Rust 代码覆盖率统计工具。竞品有:
quickcheck
afl.rs
Proptest,是一个受 Python 的 Hypothesis 框架启发的属性测试框架(即 QuickCheck 家族)
serde,最流行的序列化反序列化工具。编码类工具还有:
bincode,二进制序列化反序列化
byteorder,大小端字节序
json,JSON 序列化反序列化
html5ever,高性能 HTML5 解析器
msgpack-rust,MessagePack 的 Rust 实现
prost,ProtocolBuffer 的 Rust 实现
网络 与 Web 库
Rust 语言网络和 Web 后端框架我将其分类有四大派系:async-std 系、 tokio 系、大厂自研系和 WebAssmbly Server Side 系。
tokio 系:
tokio,算是目前 Rust 异步生态事实性的通用 Rust 异步运行时
hyper,流行的 Rust HTTP 库
reqwest,流行的 Rust HTTP 客户端
actix-web,流行的 Web 异步开发框架,同类型竞品有:
axum,基于 Tokio、
tower和 Hyper 构建的模块化的 Web 框架,注重人机工效学。poem,一个功能齐全且易于使用的基于 Rust 编程语言的 Web 框架。
rocket,一个注重易用性、安全性、可扩展性和性能的异步 Web 框架。
tonic,gRPC 的 Rust 实现,是一个高性能、开源的通用 RPC 框架,专注于移动和 HTTP/2。
async-std 系:
async-std,是由 Rust 官方团队维护开发的异步标准库。虽然应用不如 tokio 广泛,但目前还在维护中。
tide,是官方维护的异步 Web 框架,目前在缓慢维护中。如果上生产,还是建议使用 tokio 系框架。
大厂自研系:
ylong_runtime,由华为自研的 Rust 异步运行时,优势是针对于 mobile 做了特别优化。
monoio,由字节跳动自研的基于 Linux io-uring 的 Rust 异步运行时。
volo,用于构建微服务的高性能和强可扩展性的 Rust RPC 框架。
tarpc,非 Google 官方但是在 Google 官方仓库里的 gRPC Rust 框架。
WebAssmbly Server Side 系:
lunatic,是受 Erlang 影响的一个 WebAssembly 运行时。你可以使用它快速、健壮和可扩展的服务器端应用程序,但是你可以通过任意可以编译为 WebAssembly 的语言来使用它。在今年 (2023) 的 WASM I/O 会议上,有人分享了 如何使用 Lunatic 来构建高并发应用。
submillisecond 是 lunatic 在去年推出的一个 Web 框架。注重 WebAssembly 安全性,基于 lunatic 调度运行时。submillisecond 的另一个特色是支持 Liveview 。Liveview 的灵感来自于 Elixir 的 Phoenix web 框架 。LiveView 编程模型是声明式的:LiveView 中的事件不是说“一旦事件 X 发生,就在页面上更改 Y”,而是可能导致其状态发生变化的常规消息。一旦状态发生变化,LiveView 将重新渲染其 HTML 模板的相关部分并将其推送到浏览器,浏览器以最有效的方式进行自我更新。这意味着开发人员像编写任何其他服务器呈现的 HTML 一样编写 LiveView 模板,LiveView 负责跟踪更改并将相关差异发送到浏览器。
spin 是 fermyon 团队开源的一款用于使用 WebAssembly 构建和运行快速、安全且可组合的云微服务的框架。它旨在成为开始使用 WebAssembly 微服务的最简单方法,并利用 WebAssembly 组件模型 和 Wasmtime 运行时的最新发展。今年已经发布 1.0 ,旨在简化 WebAssembly 微服务。并提供了 Fermyon Cloud 服务,方便开发者快速部署 spin 应用。
Rust 也涌现了不少大前端应用开发框架和库, 2023 年还在持续增长的有:
Deno 是一个现代且安全的 TypeScritp 和 JavaScript 运行时,基于 V8 和 Rust 实现。
Promises、async/await、ES 模块和异步迭代器等在 Deno 中都是一等公民。2023 年 Deno 发布了 Deno Deploy 服务,这是 deno 官方提供的一个分布式部署环境,它可以让你的代码快速部署到全球 34 个节点,你可以不需要配置,不需要维护就快速部署好你的应用。Deno 今年正 向 Deno 2 的重大版本迈进。swc,是 Speedy Web Compiler 缩写,是一款用 Rust 编写的超快 TypeScript / JavaScript 编译器。版本依旧非常活跃地更新着。2023 年该项目作者 dudykr 又开了一个新坑 stc,是一个高性能的 TypeScript 类型检查器,虽然引来一些争议,但他还是一直在开发中。
parcel ,是一个 Rust 实现的 Web 应用打包工具,适用于经验不同的开发者。它利用多核处理提供了极快的速度,并且不需要任何配置。它基于 swc 实现。2023 年 parcel 发布了 v2.9.0 版本,该版本用 Rust 重写了依赖文件路径 resolver。parcel 还开源了一个新的 CSS 解析、转换和压缩工具 parcel-css 。
Yew 是一个设计先进的 Rust 框架,目的是使用 WebAssembly 来创建多线程的前端 web 应用。它基于组件,灵感来自于 React 和 Elm,高性能,且支持与 JavaScript 交互。目前还在活跃开发中。
sycamore 是一个响应式的无虚拟 dom 的 前端库,同样是基于 Rust 和 WebAssembly 。它的特点是,不支持 JavaScript ,因为不需要。
Turbo 是一个用 Rust 编写的前端开发的下一代工具链,由三个部分组成:
Turbopack,一种增量打包工具(Webpack 的继任者)
Turborepo,一个增量构建系统
Turbo engine,一种底层增量计算和记忆化引擎
嵌入式安全操作系统 TockOS 2.1 发布 。在 TockOS 迈向 2.0 时,许多核心的内核 API 被重新设计和重写。并且支持 11 个新的硬件平台,包括 RISC-V。TockOS 的贡献者之一 Alexandru ,创办了 OxidOS 公司,为汽车软件 OEM 和开发商提供安全操作系统和开发工具。
嵌入式与物联网
在今年(2023)首届嵌入式开源峰会(EOSS)上,由瑞士的 Zühlke Engineering 公司嵌入式工程师 Mosler 分享了 《Fearless Embedded Rust》,他和他的公司都看到了 Rust 在嵌入式项目中的潜力。
他在演讲现场展示了使用乐鑫官方推出的物联网开发框架 esp-idf 开发了一个物联网温度检测器。他用了 ESP32-C3 开发套件,采用了 RISC-V 架构,并且具备 Wifi 功能。他的 fearless-embedded-rust 代码在 GitHub 仓库。
他展示的重点是 Rust 工具链在物联网嵌入式开发领域提供了生产级可用的开发工具链和生态框架,方便构建开发环境,而 Rust 语言现代化的安全的类型系统和所有权语义也可以帮助嵌入式开发者构建更健壮的嵌入式应用。比如 Rust 的所有权模型直接映射到保留外设。也就是说,当你请求某个外设时,其他代码将无法访问它,这由编译器本身强制执行。
嵌入式生态库日益丰富:
embedded-hal,嵌入式系统的硬件抽象层(HAL),作为构建跨平台驱动程序生态系统的基础。该库已经马上要发布 1.0 了。嵌入式开发的人都知道依赖关系不协调的痛苦,这个抽象层就是为了解决这个问题,它本质是跨平台抽象。
Knurling, 是 Ferrous Systems 的一个项目,为了改进嵌入式 Rust 的体验,提供了一系列开发工具:
probe-run,允许开发者利用 Cargo 像本地应用程序一样快速运行和运行嵌入式应用程序。defmt,针对资源受限设备(如微控制器)的高效日志框架。defmt代表“延迟格式化”,可以将格式化操作推迟到将输出日志的主机上进行。flip-link,为嵌入式程序提供零成本的栈溢出保护。目前只支持 Arm Cortex-M 微控制器。
embassy ,在嵌入式中,通常使用中断、DMA 并利用多核来处理并发事件而不阻塞主循环。这些传统上是通过有意的寄存器写入来处理的。例如,向外围设备发送命令以启动任务,继续运行程序,当任务完成时,会触发一个中断,并立即运行处理完成的代码。Rust 中可以使用基于 Future 的 Async/Await 功能来抽象这些过程。
embassy-stm32,适用于所有 STM32 微控制器系列。
embassy-nrf,适用于北欧半导体(Nordic Semiconductor)nRF52、nRF53、nRF91 系列。
embassy-rp,适用于树莓派 RP2040 微控制器。
esp-rs,适用于 Espressif Systems ESP32 系列芯片。
Embassy HAL 支持在 esp-rs/esp-hal 库中,ESP32 微控制器的 no_std Rust 硬件抽象层(Hardware Abstraction Layers),这是乐鑫公司官方的库。。
异步 Wifi、蓝牙和 ESP-NOW 在 esp-rs/esp-wifi 库中。
esp-idf,是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 和 macOS 操作系统。
rustsbi,RISC-V Supervisor Binary Interface (SBI) 库。可在 M 模式或 HS 模式下运行。
为什么嵌入式软件领域目前还没有转向 Rust 呢?
目前有一些阻碍 Rust 成为嵌入式软件主流编程语言的重要因素:
硬件供应商的支持。大多数芯片供应商只支持 C 或 C++ 的硬件抽象层(HAL)、驱动程序和使用示例,而 Rust 作为一个相对较新且用户群体相对较小的语言,他们为什么要承担支持 Rust 的工作呢?Rust 嵌入式生态系统主要由社区编写的开源软件组成,公司开发从依赖硬件供应商转到依赖开源生态需要转变态度。好消息是,对于 Rust 的供应商支持正在逐渐完善。在过去几年中,Infineon (是首家支持 Rust 编程语言的主要半导体制造商,首批支持的产品包括 AURIX TC3xx 和 TRAVEO T2G 汽车 MCUs) ,以及 Espressif (乐鑫) 都开始为 Rust 开发软件开发工具和工具包。
芯片支持。Rust 嵌入式生态系统在对某些芯片的完整性甚至可用性方面存在很大差异。Rust 没有 C 语言几乎支持任何架构的优势,但即使 Rust 支持微控制器的架构,可能也没有相应的 HAL 可用,或者可能是不完整的。尤其是较新的芯片更容易受到这个问题的影响。当然,这种情况也在好转,很多公司愿意为开源贡献生态缺失的 HAL,比如 Tweede golf 公司。
Rust 开发者缺乏。这是一个“鸡生蛋还是蛋生鸡”的循环引用问题。很多公司能预见到 Rust 潜力,并且相信公司未来会转到 Rust ,但是,因为很难找到擅长 Rust 的开发人员,所以这个转型进程就一直拖延着。然而,如果几乎所有嵌入式开发工作都是给 C 或 C++ 开发人员的,开发人员为什么要投入大量时间学习 Rust 呢?所以,需要打破这种“鸡和蛋”的循环才行。
RTOS vs Embedded Async
多年来,实时多任务操作系统 (RTOS) 一直是嵌入式应用软件的基础和开发平台。而 Rust 带给嵌入式开发的现代化的开发特性是异步编程,有希望可以更好地替代 RTOS。
Tweede Golf 团队对这两者进行了对比,嵌入式 Rust 使用了嵌入式异步运行时 Embassy。Embassy 可能是嵌入式系统中最受欢迎的异步执行器它还为许多热门的微控制器提供了完全实现的硬件抽象层(HAL)。
异步 Rust 的最大好处之一是更小的 RAM 占用。传统的实时操作系统(RTOS)需要为每个任务分配一个堆栈。Rust 的 futures 只需要跟踪在 await 点之间使用的变量。这意味着异步任务所需的内存可以比传统的 RTOS 任务小得多,对于较简单的任务,甚至可以只有几十个字节!这意味着异步可以启动更多具有较小离散工作的任务,而不是将多个职责过载到单个任务中。
另一个好处是任务之间没有上下文切换。由于在一个协作调度的环境中运行,当任务处于挂起状态时,不需要保存和恢复任务的状态。这意味着异步可以花更多时间做有用的工作,而不是上下文切换!
当然异步也有它的缺陷,异步不方便调试,栈展开并不完全符合预期。另一个不足是协作调度的方式没有优先级,但是可以通过使用中断自己的优先级,每个中断都会运行一个执行器。这种方式实现了基于优先级的调度,但与传统的抢占式实时操作系统相比,增加了相当多的复杂性。
异步 Rust 是嵌入式系统的强大工具,使开发者能够编写易于理解且占用内存较小的并发代码。尽管它也有一些缺点,但在我看来,其优势远远超过了成本。
图形处理
Rust 生态中也有很多图形处理和 UI 框架,在往年的盘点中也介绍了不少。本文挑选一些重点项目来看看它们今年的进展。
gfx-rs wgpu 生态蓝图
wgpu 适用于 GPU 上的通用图形和计算。使用 wgpu 的应用程序可以在 Vulkan、Metal、D3D12, D3D11, 和 OpenGL ES 上原生运行;在 wasm 上使用 WebGPU。该 API 基于 WebGPU 标准。它是 Firefox、Servo 和 Deno 中 WebGPU 集成的核心。
gfx-rs 团队在 2023 年没有公开什么动态,但是从代码仓库的 Changelog 看,团队一直在积极更新。
游戏领域
EmbarkStudios 公司开源的 rust-gpu 今年发布了 0.9 版本。虽然该项目目前许多东西还没有实现,还远远没有达到可以投入生产的程度,但是该项目的前景是相当不错的。在游戏中,GPU 编程以往都是通过编写 HLSL 或在较小程度上编写 GLSL 完成的。这些都是简单的编程语言。然而,随着游戏引擎的发展,这些语言未能提供处理大型代码库的机制。Embark 凭借拥有优秀的渲染工程师团队,希望通过将现有的、低级别的、安全的、高性能的 Rust 语言带到 GPU 上,来推动这个行业的发展。而随之而来的是一些不可忽视的额外好处:一个业界最好的包 / 模块系统,针对竞赛条件或越界内存访问的内置安全,广泛的工具和实用程序,以改善程序员的工作流程,以及其他许多东西。
rust-gpu 项目为 rustc 编译器后端生成 SPIR-V,通过-Z codegen-backend插入。这与rustc_codegen_cranelift和rustc_codegen_gcc使用的机制相同。目前只计划支持 SPIR-V,Vulkan 的开放编译器目标。未来的版本可能会支持 DXIL(DirectX 的目标)或 WGSL(WebGPU 的着色语言,与 SPIR-V 是双投影的)。
Bevy 是一个用 Rust 构建的简单得令人耳目一新的数据驱动的游戏引擎。拥有现代化且可扩展的 2D 和 3D 渲染器,一流的 ECS(实体组件系统)令人愉悦地使用,拥有丰富的功能,并且拥有充满活力和开放的开发者社区。目前,它支持 Windows、MacOS、Linux、iOS 和 Web。我们还在进行 Android 支持的工作……并且未来还有更多平台的雄心壮志!
bevy 在 2023 年截止目前,发布了 0.11 版本,其中有一些重要更新:
WebGPU 支持:Bevy 现在可以使用现代的 WebGPU Web API 在 Web 上更快地渲染,并具备更多功能
即时模式 Gizmo 渲染:轻松高效地渲染 2D 和 3D 形状,用于调试和编辑器场景
ECS API:Schedule-First ECS APIs和ECS Audio APIs
网格 UI 布局:Bevy UI 现在支持 CSS 风格的网格布局
改进的着色器导入:Bevy 着色器现在支持细粒度导入和其他新功能
ECS Schedule v3:Bevy 现在具有更简单、更灵活的调度功能
环境贴图照明:360 度环境图像照明,可以以低成本且显著地提高场景的视觉质量。
改进的 Android 支持:Bevy 现在可以在更多的 Android 设备上直接使用(有一些注意事项)
ECS 优化:同样地,我们对许多常见的 ECS 操作进行了加速。Bevy 应用程序将获得良好的速度提升!
pixels 一个轻量的硬件加速的像素帧缓冲器。使用 pixels 可以迅速为一个简单的 2D 游戏、基于像素的动画、软件渲染器或你最喜欢的平台的仿真器制作原型。建立在由 wgpu 驱动的现代图形 API 上:Vulkan、Metal、DirectX 12、OpenGL ES3。对 DirectX 11、WebGL2 和 WebGPU 的支持还在进行中。
图形编辑器与渲染
Graphite 是一个 Rust 实现的轻量级的光栅和矢量 2D 图形编辑器,它是免费和开源的,可以用于浏览器中。它的目标是重新定义图形编辑。在今年 2023 年全球进入 AI 时代的潮流之下,它也选择加入了 AI 功能。它的初级基于节点的合成器可以让开发者应用光栅效果,并与人工智能共同创作令人惊叹的艺术作品,而且工作流程是非破坏性的。目前,正在全力开发功能齐全的光栅图像编辑和本地桌面应用程序,并将在未来几个月内推出。
lyon 一个用 Rust 编写的路径细分库,用于基于 GPU 的 2D 图形渲染。目前 lyon 正式发布 1.0 版本。lyon 从 2016 年开始开发,之所以迟迟发布 1.0 ,是因为作者希望 lyon 成长为一个功能齐全的 2D 渲染器。在达成这个目标的过程中,作者发现开发一个快速而健壮的曲面细分器本身就是一个大项目,所以就有了现在的 1.0 。2023 年 lyon 缓慢维护着,作者受 zig 语言影响开始钻研 Rust 中如何实现自定义分配器,并且在 lyon 的 tessellator 中尝试。
大数据、人工智能与科学计算
图计算
阿里巴巴 GraphScope 交互式引擎(GIE),是一个分布式系统,专门设计用于方便各种用户以探索性的方式分析大型复杂图结构。它利用 Gremlin 提供高级语言进行交互式图查询,并提供自动并行执行。其中 查询 executor 使用 Rust 开发,极大地增强了其性能。
分布式流处理引擎
arroyo,与 Apache Flink 流处理工具竞争的 Rust 流处理引擎,Arroyo 官方声称比 Flink 性能快 10 倍。可用于实时的数据处理。
深度学习框架
burn 是一个新的深度学习框架,支持 CPU 和 GPU,使用新的 Rust 特性 GAT 功能来支持多个后端作为插件。
作者如是说:“总的来说,我一开始并没有 GAT,但我很快意识到有它比没有它要容易得多。”
这个库旨在成为一个用 Rust 编写的具有极高灵活性的且完整的深度学习框架。目标将是满足研究人员和从业者,使实验、训练和部署您的模型更容易。
用 Rust 编写的其他机器学习框架要么限制性太强(比如要求在编译时就知道矩阵的大小),要么 API 不够理想,要么缺少关键的功能,比如 GPU 支持。Burn 不一样,Burn 基于Backendtrait 架构来支持不同的后端。Burn 的目标是使创建优化的后端非常容易,并支持不同的设备和使用情况。目前,只有 3 个后端。NdArray 是一个纯粹的 Rust 解决方案,Tch 是一个易于访问 CUDA 和 cuDNN 优化的操作,ADBackendDecorator 使任何后端都可以区分。Burn 现在正在重构内部的后端 API,使其尽可能容易插入新的 API。
2023 年 burn 又支持了新的 GPU 后端,利用 wgpu 自动支持 Vulkan、OpenGL、Metal、Direct X11/12 和 WebGPU。
Rust 与大语言模型
llama2-burn,又将 Meta 最新发布的开源大型语言模型 Llama2 移植到 Rust 深度学习框架 Burn 上。这个项目也引起了 Graphite 图形编辑器团队的注意。
Graphite 团队表示,对 Python 的不可移植性感到相当沮丧。拥有一个纯 Rust 实现将是一个很好的解决方案(而 Burn 甚至比 tch-rs 更纯粹,后者是对 PyTorch C++ API 进行 FFI 绑定)。对于我的使用情况来说,可移植性和纯 Rust 非常重要... Graphite 团队表示将开始为 Stable Diffusion 迁移到 Rust 实现,除了原始论文之外,还有数十个额外的功能,这些功能增加了有用的能力(ControlNet、嵌入、Dreambooth、LoRA、不同的模型版本、xformers 等),将它们移植到 Rust 需要一些努力。由于我目前在 Graphite 开源团队担任产品经理的职务,我也可以担任一个团队的产品经理,负责 Stable Diffusion 的移植工作,以实现与最先进的 Python 发行版(如 AUTOMATIC1111)完全功能相同的移植,以协调对 Rust 开源生态系统、Burn 和 Graphite 的利益有益的团队的努力。可能从小规模开始(如 MiDaS、ESRGAN 等),然后逐渐转向 Segment Anything,再稍后移植 Stable Diffusion,以便团队积累一些经验。
llm,是一个用于处理大型语言模型的 Rust 库生态系统 - 它是基于快速高效的 GGML 机器学习库构建的。llm由ggml张量库提供支持,旨在将 Rust 的稳健性和易用性带入大型语言模型的世界。目前,推理仅在 CPU 上进行,但后续希望通过备用后端在将来支持 GPU 推理。
Chidori 是一个 LangChain 的替代品,同样可以方便的构建 AI Agent,主要优势是反应式编程。由 Rust 开发,能支持 Python、Nodejs 和 Rust 构建 Agent。它目前处于 alpha 阶段,尚未准备好投入生产使用。以下是它的一些特点:
从头开始构建代理
运行时由 Rust 编写,开箱即支持 Python 和 Node.js
构建可实际运行的代理
LLM 缓存可最大限度地降低开发成本
针对长时间运行的人工智能工作流进行了优化
嵌入式代码解释器
支持时间旅行调试
qdrant,是 Rust 实现的一个开源向量数据库。向量数据库作为大语言模型的「长期记忆」能力,当下很火。qdrant 目前融资 750 万美元种子轮。而在向量数据库业内的独角兽公司 Pinecone 用 Rust 重写数据库之后,B 轮融资 1 亿美元。传统数据库可以通过添加向量存储和向量搜索来提供向量数据库的功能,但是面对海量数据量,想要平衡向量搜索的准确度和性能,还需要专门的向量数据库。Qdrant (商业开源)和 Pinecone (商业闭源)就是专业的向量数据库。从 Qdrant 的实现看出,其在向量内存占用优化和向量海量搜索算法上下了不少功夫。内存占用优化使用 Product Quantization(乘积量化) 技术,使用 K-Means 聚类算法来平衡准确性和搜索性能。
async-openai 是 OpenAI REST API 的非官方 Rust 绑定,基于 OpenAPI 规范 。当 API 服务器 限制速率 时,将使用指数退避重试非流式请求。
Mithril Security 公司开源了 BlindAI,这是一种用于机密推理的开源 AI 部署解决方案。如今,大多数 AI 工具的设计机制都没有提供隐私保护,因此当数据被发送给第三方进行分析时,数据可能会遭到恶意使用或可能泄露。与常规 AI 推理解决方案一样,BlindAI 帮助 AI 工程师为最终用户提供模型以从他们的预测中受益,但增加了隐私层。用户发送给 AI 模型的数据从传输到分析始终保密。这样,用户就可以从 AI 模型中受益,而无需向任何人公开他们的数据:AI 服务提供商和云提供商(如果有)都看不到这些数据。
tokenizers 是 Hugging Face 公司开源的一款 Rust 实现的分词库。基于深度学习的现代 NLP 管道中的瓶颈之一就是 tokenization,尤其是通用性强且独立于框架的实现。所以,该分词器的核心是用 Rust 编写的,并且存在 Node 和 Python 的绑定。提供当今最常用的分词器的实现,重点是性能和通用性。
faer-rs 是一个用 Rust 实现的线性代数例程的 crates 集合。目标是为线性代数提供一个功能齐全的库,重点关注可移植性、正确性和性能。目前还在活跃开发中。
云原生 与 WebAssembly 趋势
在往年的 Rust 生态报告中我也罗列了不少 Rust 在云原生方向的开源应用,今年主要关注下 WebAssembly 在云原生的进展,因为 2022 年底由 CNCF wasmCloud 的联合创始人兼 Cosmonic 的首席执行官 Liam Randall 预测,2023 年云原生开发将由 WebAssembly 引起巨大变革。
今年 4 月在阿姆斯特丹举办的 KubeCon 欧洲大会,对 WebAssembly 总体趋势有一些反映:
WebAssembly 组件模型提供了语言支持、互操作性以及在编写软件方面的巨大潜力。与仅仅一年前组件模型还是一个新概念相比,我们现在已经看到了组件模型的演示。
Serverless 是 WebAssembly 一个重要应用领域。
Wasm 非常适合插件系统,比如 vst-rs,附加关于 WASM 作为通用插件系统相关文章。
Docker 正在努力支持尽可能多的 Wasm 运行时,目前的列表包括:spin, slight, Wasmtime, 和 WasmEdge。
k8s 支持 wasm 构建微服务,比如 spin 支持 k8s 。
WebAssembly(Wasm) Server Side 的趋势
目前 WebAssembly(Wasm)生态系统正在发生变革。开发者可以期待一个模块化、可虚拟化和强大的环境,用于构建应用程序、库和服务。
字节码联盟整理了一份 WebAssembly 精简路线图。
这个路线图反映了 WebAssembly 社区组(CG)和 W3C 的 WASI 子组中标准的变化,包括 WebAssembly 核心、WebAssembly 组件模型、WASI(WebAssembly 系统接口)以及一系列基于 WASI 的接口。
核心规范概述了构建 WebAssembly 模块的基础。一些正在进行的重要工作包括:
由 Conrad Watt、Andreas Rossberg 和 Andrew Brown 开发的 Core Wasm Threads 原型,添加了一种新的共享线性内存类型和用于原子内存访问的新操作。
WebAssembly 垃圾回收正在由 Andreas Rossberg、Ivan Mikushin 和 Nick Fitzgerald 进行研究。
WebAssembly 组件模型旨在解决语言互操作性问题,它提供了语言无关的、可组合的、可互操作的、可平台虚拟化的 Wasm 组件。组件模型在核心规范之上开发,包括 WebAssembly 接口类型(WIT)IDL。WIT 是我们用来描述组件接口的高级类型的语言。
WASI 建立在组件模型和核心 WebAssembly 规范之上。WASI Preview 2 将包含至少两个 World 定义,包括 CLI-world 和 HTTP Proxy world。
一些新功能展望:
Rust 语言提供了 Cargo Component ,允许通过 Cargo 命令方便地创建 WebAssembly 组件。
云原生软件的核心构建模块,通过模块化 WASI 接口 将各种云原生接口整合在一起,比如 wasi-keyvalue, wasi-messaging, wasi-sql 和 wasi-blob-store
Rust 与 跨平台开发
Rust 非常适合跨平台开发。你可以轻松地编写全面的测试套件,运行时间仅为毫秒级。你可以将其与任何本地 UI 框架结合,并将其部署到 Web(使用 WebAssembly)以及 iOS 和 Android(使用 FFI)甚至桌面端(macOS/Linux/Windows)。
往年也介绍过一些开源 Rust 的跨平台 UI 库或框架,下面主要介绍一些 2023 年出现的跨平台框架:
Crux 框架,以帮助开发者充分利用 Rust 的表达能力和每个平台的惯用的 UX/UI 框架。目前为实验性项目。特色是:
它将应用程序分为两个明确的部分:一个由 Rust 构建的核心,尽可能驱动业务逻辑,以及一个由平台本地语言(Swift、Kotlin、TypeScript)构建的 shell,提供与外部世界的所有接口,包括人类用户,并充当核心运行的平台。
两者之间的接口是一个本地的 FFI(Foreign Function Interface),具有跨语言类型检查和消息传递语义,简单的数据结构在边界上传递。
架构是事件驱动的,基于事件溯源。核心部分保存了大部分状态,这些状态会根据 Shell 中发生的事件进行更新。核心部分和 Shell 之间的接口是基于消息的。
用户界面层是使用现代声明式 UI 框架(如 Swift UI、Jetpack Compose 和 React/Vue)或基于 Web 的 WASM 框架进行本地构建的。用户界面层尽可能地薄,所有其他应用逻辑由共享的核心层执行。
Makepad ,基于 Rust 实现,用于构建本地 UI 和 Web 的框架,目前仅支持 Mac 和 Web 平台,未来会支持更多平台。组成:
makepad platform,是 Makepad 的主要平台抽象层,最大的特色是 Live System,可以在运行时更新 Makepad 应用程序。另外还包含 Makepad 自定义着色语言 MPSL 。
makepad draw,支持 2D 和 3D (即将支持)绘制。
makepad widgets,包括一个可从 DSL 设计的保留模式 Widget 系统设计,以及一组基本 Widgets(按钮、滑块、复选框、列表等)。特点是 每个 Widget 都可以确定自己的渲染模型,无论是即时模式、保留模式,还是通常的混合模式。
Makepad Framework,UI 框架,完全在 GPU 上渲染,并支持一种称为 live design 的新颖功能。该 UI 框架又由三部分组成:
Makepad Studio,一个具有实时设计感知能力的 IDE 原型,可以检测到 DSL 代码的更改,而不是 Rust 代码的更改,从而使应用程序能够自动更新自身。使用 Makepad Framework 构建。
1Password 也开源了其 跨多种语言生成一致的类型模式 的 Typeshare 库。Typeshare 可以帮助开发者实现跨语言无缝同步共享数据类型,这是跨平台安全开发的利器。
跨平台框架探讨
在今年的 EOSS 2023 大会中,编译器黑客 Andy 从编译器角度探讨了,现代应用开发框架,包括特定平台的 SwiftUI 和 Jetpack Compose,以及跨平台的 React Native、Flutter 和其他基于 JavaScript 的跨平台框架之间,在编程模型、语言设计和性能之间的关系。
以下是一些关键点:
跨平台应用框架的设计:作者强调了应用开发者和框架开发者之间的分工,应用开发者决定“什么”,框架开发者决定“如何”。这是一种风险的交易,因为框架的设计和实现决定了应用的性能和功能。
框架限制性能的四种主要技术:管理状态、增量渲染、并发渲染和并发垃圾收集(GC)。
Rust 的声明式 UI:作者提到了 Dioxus,这是一个实验性的具有 WebGPU 后端的 Rust 声明式 UI 框架。
WebAssembly 和 WebGPU 的未来:用户应用是 Wasm 模块,它们导入 WebGPU 等功能。WebAssembly 2.0 的 GC 有助于实现高效的互操作性。
作者对 Rust 的跨平台 UI 框架的看法可以从以下几点进行总结:
声明式 UI 已经取得了胜利,这是一个不可逆转的趋势。这意味着未来的 UI 框架,包括 Rust 的跨平台 UI 框架,都会倾向于采用声明式的设计。
框架会限制性能。这是一个需要注意的问题,尤其是在设计跨平台 UI 框架时。因此,Rust 的跨平台 UI 框架需要考虑如何在保证易用性的同时,尽可能地提高性能。
在跨平台应用开发领域,React Native 和 Flutter 是强有力的竞争者。但是,作者认为还有更多的空间可以发展,Rust 的跨平台 UI 框架也有其存在的价值和可能。
作者预测,在未来两年内,Flutter 可能会采用 Rust 作为其实现语言;在未来五年内,可能会出现对 TypeScript 进行静态类型检查的工具。
总的来说,作者认为 Rust 的跨平台 UI 框架有其存在的价值和可能,但是也需要注意到框架可能会带来的性能限制,并需要考虑如何在设计中解决这个问题。同时,也需要关注其他的跨平台应用开发框架,如 React Native 和 Flutter,从中学习和借鉴。
Rust for Linux 状态
Rust 从 Linux 6.1 进入 Linux 内核开始一路跟随 Linux 内核版本到 6.5,首次将 Rust 语言工具链升级到 Rust 1.68.2。
就在前几天,Miguel Ojeda 发布了升级 Rust 代码至 Rust 1.71 版本的 补丁。从 1.68 到 1.71 系列,内核使用的不稳定特性都得到了稳定(唯一允许在kernelcrate 之外使用的不稳定特性仍然是new_uninit)。然而,这次升级确实需要对内核代码进行一些小的更改,主要是为了让 linux kernel crate 中 fork 的上游的allocapi 能和上游一致。
今年 3 月份,Asahi Lina 发布了一个基于 Rust 的 Apple AGX(M1 和 M2 系列芯片中的 GPU)图形处理器驱动程序的初始版本;该发布包含了一定数量的用于图形驱动程序的 Rust 基础设施。去年 8 月份,Asahi Lina 给 Rust for Linux 邮件组发了一封邮件,陈述了她用 Rust 给 Apple AGX 图形处理器实现 Rust 驱动。
4
深入 Rust 商业应用
Rust 在全球商业巨头中的应用
随着 2022 年底 Google Android 团队宣布 Android 13 已经取得了 Rust 内存安全零 Bug 的目标,Google Chromium 项目也在 2023 年 1 月官宣将在 Chromium 项目中支持 Rust 第三方库。
目前 Chromium 团队正在积极地将 Rust 工具链集成到其构建系统中(实际上这项工作已经持续很久了),在明年(2024?)内将 Rust 代码包含在 Chrome 二进制文件中。
为什么选择将 Rust 引入 Chromium?
为了提供一种更简单(无 IPC)和更安全的方式来满足加快开发速度(更少的代码编写,更少的设计文档,更少的安全审查)并提高 Chrome 的安全性(增加没有内存安全错误的代码行数,降低代码的错误密度)的需求。
Chromium 将如何支持 Rust 的使用?
目前,Chromium 将只支持单一方向的互操作,即从 C++ 到 Rust。Chromium 是用 C++ 编写的,大部分的框架技术栈都是 C++ 代码,通过将互操作限制在一个方向,可以控制依赖树的形状。Rust 不能依赖 C++,所以它不能知道 C++ 的类型和函数,除非通过依赖注入。
暂时只支持 Rust 第三方库。第三方库是作为独立的组件编写的,它们不持有关于 Chromium 实现的隐含知识。这意味着它们的 API 更简单,而且专注于它们的单一任务。
Chromium 中 Rust 和 C++ 之间的互操作
迄今为止,大多数成功的 C/C++ 和 Rust 互操作故事都是围绕着通过单一 (Narrow) 的 API(如 QUIC 或蓝牙的库,Linux 驱动程序)或通过明显的隔离组件(如 IDL,IPC)进行互操作。Chrome 是建立在基础的但真正广泛的 C++ API 上的,在高层次上,团队发现,由于 C++ 和 Rust 遵循不同的规则,事情很容易出岔子。例如,Rust 通过静态分析来保证时间上的内存安全,静态分析依赖于两个输入:生命期(推断的或明确写入的)和独占的可变性。后者与 Chromium 的大部分 C++ 的编写方式不兼容,在整个系统中持有冗余的可变指针,以及提供多条路径来到达可变指针的指针。这在 Chrome 浏览器进程中尤其如此,它包含了一个巨大的(可变)指针互连系统。如果这些 C++ 指针也以复杂或长期的方式被用作 Rust 的引用,这就要求 C++ 作者理解 Rust 的别名规则,并防止违反这些规则的可能性。

