Rust – 系统级语言的首选

2022年 Linux 内核正式支持使用 Rust 开发,在 Rust 社区引起了广泛的讨论,这个事情把 Rust 这个看起来小众的计算机语言提高了很大的曝光度。也让更多人明白,Rust 并不是一个极客的玩具,而是系统领域一个新的生产力编程语言。

2022年还有一个重要的小事件,微软云 (Azure) CTO 在 Twitter 宣布,以后新开发的项目,如果需要采用不带 GC (内存垃圾回收)的语言,都应该采用 Rust,甚至号召业界宣布其他语言应该被放弃。

业界的各种发展,意味着 Rust 已经真正成熟了。

Rust 历史

Rust 由 Mozilla 基金会于 2006 年开始开发,最初定位是 “更好的 C++”,为了 Mozilla 编写新的浏览器引擎 Servo。

随着 Rust 的发展,现在已经脱离 Mozilla 基金会。并且,Rust 现在发展得很成功,反倒是 Servo 这个项目基本已经停滞了。

Rust 的特点

内存安全性

Rust 使用所有权(ownership)、借用(borrowing)和生命周期(lifetime)等概念来实现内存安全性。这些概念使 Rust 在运行时能够准确地跟踪内存的使用情况,从而在编译期就发现并防止许多内存错误。比如缓冲区溢出、空指针引用和数据竞争等。这类问题在之前的系统语言里面经常发生。

零成本抽象

Rust 可以提供与 C++ 相媲美的高性能,同时又允许开发者使用高级抽象特性。Rust 采用了零成本抽象的设计,这意味着在 Rust 中使用高级特性不会影响程序的性能。例如,Rust 中的闭包、trait 和泛型等特性不会引入运行时开销。

并发性

Rust 对并发性提供了内置支持异步(async)函数,这是一个非常重要的特点。Rust async 可以把几乎任何函数都定义为异步,这样在需要等待一个 IO 处理时,及时交出 CPU,可以让 CPU 继续执行其他任务,并且不会陷入异步 IO 框架的回调地狱

生态系统

Rust 的工具链 Cargo 使得管理依赖非常方便。随着第三方库的积累,Rust 目前的第三方库已经非常丰富。

实际使用体验

从 2015年 就开始关注 Rust 的发展,直到 2019年,Rust 正式支持 Async/await,感觉 Rust 已经成熟了,是时候开始尝试用 Rust 来做点东西。

所有权管理带来安全,但是很多人觉得麻烦

Rust 一开始最重要的特性就是所有权,基于所有权机制,Rust 强制要求开发人员在开发阶段就规划好每一个内存的使用,考虑到 C/C++ 开发的应用,80% 左右的问题,都是内存不安全带来的,总体上是提高了效率。但是,在开发阶段,由于很多人的代码编译通过要费很大劲,所以除了带来麻烦,也并不能体会到效率提高,这估计是很多人只感觉到带来麻烦,没有什么收益的直接原因。也是很多人从尝试到放弃的直接原因。

Async/Await 的成熟,带来彻底改变

一个稍微有点规模的应用,都会面临大量的处理异步请求的问题。之前这方面表现能力最强的,就是 C# 和 JavaScript 的 Async/Await 机制。

系统语言层面的 epoll + 状态机、各种 异步IO 框架,都把业务代码撕裂到各个碎片回调里,IO 源和状态多了,业务逻辑非常零碎,代码几乎没法维护。

而 Rust 把 JavaScipt 上非常好用的 Async/Await 引入,并且运行态开销等于协程的开销,相当于用 JavaScript 的语法,写出协程的性能。这个是我当时开始尝试 Rust 的最大诱因

用类似 JavaScript 的编写效率,写出系统级别运行效率的应用,这是目前 Rust 最突出的特征。

直接尝试的效果

目前用 Rust 写了 2 个重要系统,一个是网络代码模块,一个是 IoT 平台。

替换 C/libev, 再也不想用 libev 来写任何东西了

网络代理模块之前采用 C 语言,基于 libev 编写,最大的问题是维护非常麻烦。花了不多的时间,用 Rust 重新改写了一遍,除了代码量大幅下降,以前代码几乎没什么可读性,换一个人很难看懂。现在的代码,读起来跟读 JavaScript 差不多。

另外还有超过预期的收获,之前 C/libev 实现,高峰期 CPU 负荷平均 80%,而采用 Rust 改写后,平均值降到了 15%。或许 libev 的实现,做下深度优化也能提升,但是 Rust 的版本编译通过后就直接做压力测试,没有另外花时间调优。

异步 IO 框架,每多一个状态,代码的复杂度大幅提升,心智负担很重。但是 Rust 没有这个问题。

改写 IoT 平台,完美契合 IoT 场景

我们的 IoT 平台,经过多次重构,分别有 node.js, Erlang, Java 的版本,这些方案各有优缺点。node.js 写起来很方便,但是编写大型后端系统还是有很多问题,比如内存使用会非常高。Erlang 并发性非常好,但是 CPU 效率比较低,内存使用也偏高。Java GC 会卡顿,高峰期内存压力也很大。

自从用 Rust 重构后,大量的采用 Async/Await 完成业务逻辑,几乎函数默认都是异步的,语言表现力上几乎等同于 JavaScript,异步性能超过 Erlang 的表现(当然,异步机制不一样),也完全没有 GC 卡顿问题。

从 CPU 的负载、内存使用量、响应延迟多个方面,都有最完美的表现。

另外,IoT 系统的 Web 管理后台 API,也用 Rust 重构,比起目前主流的 Spring Boot,Rust 版本明显响应速度更快,内存使用更少。实际开发效率也不会比 Spring 差,反倒是 Rust 的 Actix Web 框架没有 Spring 很多过度设计的特性,更容易控制。

前景和问题

正在快速发展的领域

  • Linux 内核支持后,可以预期有越来越多的内核模块采用 Rust。
  • 微软云 IoT 全部采用 Rust。
  • 在区块链领域也有重大发展。
  • 前端方面全面支持 WebAssembly。
  • 嵌入式领域可以很好的替代 C/C++。
  • Firefox 浏览器越来越多模块采用 Rust 编写。
  • Android 也要加入支持 Rust。

虽然各方面发展势头不错,但是面临一些问题。

问题,“很难”学会

Rust 虽说各方面都有很好的表现,但是什么时候能被大多数团队采用,还有待观察,特别是在国内。

其他语言学个一知半解,可能就可以上手尝试(虽说实际是给后面埋下大量隐患)。而 Rust,几乎要求开发人员完全理解内存管理机制,才能写出一个能编译通过的应用。

而目前学校的教育水平、从业人员实际情况,很多人并不真的理解内存管理原理,会造成上手入门非常困难。再加上 Rust 在内存安全的基础上,衍生出了很多新的概念,更加大了难度。

另外还有很多人说的编译慢的问题,建议直接买一个好点的电脑。编译器做的工作多了,慢一点是很正常的。