添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
【下篇】2021 年 Rust 生态版图调研报告 | 星辰大海

【下篇】2021 年 Rust 生态版图调研报告 | 星辰大海

文前

半年前,我写了一篇 《三万言|2021 年 Rust 行业调研报告》 ,内容主要围绕 Rust 语言介绍 和 行业领域开源应用盘点 两大部分内容。时隔半年,我觉得有必要再写一篇年终的Rust 生态调研报告。因为我想给大家提供一个比较全面的视角,通过挖掘互联网上的各种散落且隐藏的信息,最终绘制出一张 Rust 的“生态地图”,让大家尽量客观公正地去认识 Rust 语言。

在完成本篇报告之后,我得出一个观点: Rust 的出现并不是要你去用它重写一切,而是希望你可以用它创造新的未来 。当然这只是我个人观点,不代表任何人任何机构和公司。如果您有不同观点,欢迎探讨。

We choose to use Rust, not because it is easy, but because it is hard, because that goal will serve to organize and measure the best of our energies and skills, because that challenge is one that we are willing to accept, one we are unwilling to postpone, and one which we intend to win, and the others, too.
我们选择 Rust ,不是因为它容易,而是因为它难。这会有助于我们去组织和衡量将精力和技能投入到一个最佳目标。当我们接受这份挑战之后,就代表这份挑战是我们愿意接受的,且愿意马上投入的,并且必须打赢的挑战。其他挑战也当如此。

本次报告的所有内容都来自于互联网公开信息,如有错误或不宜在本报告中提及的内容,请及时告知。

大纲

本次报告包含以下内容:

  • Rust Project 自身状态
  • Rust 在各个领域中的应用状态和趋势
  • Rust 职业岗位分布
  • Rust 语言在教育的普及状态

上篇回顾

在《【上篇】2021 年 Rust 生态版图调研报告 | 星辰大海》 中,我们盘点了 Rust Project 自身的状态 以及 Rust 在操作系统、云原生、物联网、游戏和数据处理领域中 2021 年值得关注的项目动态。

这篇内容会紧接上篇内容,继续探讨 Rust 在其余领域中的应用状态、Rust 职业岗位分布 和 Rust 语言在教育方面的普及状态。

Rust 在各个领域中的应用状态和趋势【续】

机器学习与科学计算

2021 年 NLP 领域明星项目 Transformers

Hugging Face 是一家总部位于美国纽约的聊天机器人初创服务商。该公司在 NLP界鼎鼎大名,2021 年 3 月份刚刚完成4000万美元B轮融资。在GitHub上发布了开源 NLP 库 Transformers ,而 Transformers 库集成了 tokenizers。

tokenizers 是 Hugging Face 公司开源的一款 Rust 实现的分词库,只需不到20秒即可用服务器CPU进行1GB文本处理。基于深度学习的现代 NLP 管道中的瓶颈之一就是tokenization,尤其是通用性强且独立于框架的实现。所以,该分词器的核心是用Rust编写的,并且存在Node和Python的绑定。提供当今最常用的分词器的实现,重点是性能和通用性。

目前 Transformer 模型预测已经遍布特斯拉、谷歌、微软、Facebook 等科技巨头。Transformer 在特斯拉 AutoPilot 自动驾驶系统中驱动汽车、在 Gmail 中补全句子、在 Facebook 上及时翻译用户的帖子以及在 Bing 中回答用户的自然语言查询等。

可以说,Hugging Face 这家创业公司 使用 Rust 来构建分词器,对于机器学习模型的准确率和性能方面的巨大提升应该是有积极作用等。

linfa

Linfa 是一个 Rust 实现的 类似于 python scikit-learn 的库,旨在提供一个全面的工具包,可以使用 Rust 构建机器学习应用程序。该团队还创建了 Rust-ML 组织。

“ scikit-learn,又写作sklearn,是一个开源的基于python语言的机器学习工具包。 它通过NumPy, SciPy和Matplotlib等python数值计算的库实现高效的算法应用,并且涵盖了几乎所有主流机器学习算法。

更多资料: Rust 机器学习之书

2021 年该库已经发布了 0.5 版本,其 Roadmap 中 24 个任务,截止目前已经完成了 20 个。该 Roadmap 的目标就是在功能方面要和 Python 的 scikit-learn (基于SciPy针对机器学习领域发展出的一个分支版本)提供的算法完全一致。目前仅剩下 高斯过程、随机森林、集成学习和 最小角度回归没有完成。这个 Roadmap 进行了大概两年开发,预计 2022 年应该会完成。

也就是说,在 2022 年,Rust 生态中会出现一个功能和 python sklearn 完全一致,但性能比sklearn更好的库。

Polars

在数据操作层面,每个人都喜欢 Pandas 的 API。它快速、简单且有据可查。但在生产方面,Pandas 有点棘手。Pandas 不能很好地扩展……没有多线程……它不是线程安全的……它不是内存效率。这一切都是 Rust 存在的理由。

Polars 用 Rust 实现的新 Dataframe 库,具有方便的 Python 绑定。它试图做到以 线程安全的方式 进行读取、写入、过滤、应用函数、分组和合并。它使用 Apache Arrow ,这是一个专门为跨语言进行高效数据处理和数据共享而构建的数据框架。

Polars 有两个优势:

  1. 它是性能杀手,参考 db-benchmark
  2. 它的 API 非常简单。哪怕不懂 Rust 语法也能看懂该接口要做什么。

也有三个缺点:

  1. 构建 Dataframe API 很困难,Pandas 花了 12 年才达到 1.0.0,而 Polars 很年轻,所以目前还不够成熟。
  2. 使用它的时候,不仅仅要熟悉 Polars API,还需要熟悉 Arrow API,因为很多繁重工作是 arrow 来完成的。
  3. 编译时间太慢,可能需要 6 分钟左右。

Polars 现在由 Xomnia 公司赞助。Xomnia 是荷兰一家人工智能公司,在研究自动驾驶船只,被人称为水上特斯拉。

oxide-enzyme

oxide-enzyme 也是 linfa 团队在 2021 年底新创建的另一个项目。 oxide-enzyme 是 Enzyme 的 Rust 前端库,该库目前是实验性的,但在积极开发中。

Enzyme 是 MIT 提出的自动微分框架,它能够合成以 LLVM 中间表示(IR)表示的静态可分析程序的梯度。Enzyme 能够合成任何以面向 LLVM IR 编译器为语言编写的程序的梯度,包括 C、C ++、Fortran、Julia、Rust、Swift、MLIR 等,从而提供这些语言的本机 AD 功能。

Enzyme 出现的背景

当前,PyTorch、TensorFlow 等机器学习框架已经成为了人们开发的重要工具。计算反向传播、贝叶斯推理、不确定性量化和概率编程等算法的梯度时,我们需要把所有的代码以微分型写入框架内。这对于将机器学习引入新领域带来了问题:在物理模拟、游戏引擎、气候模型中,原领域组件不是由机器学习框架的特定领域语言(DSL)编写的。因此在将机器学习引入科学计算时,重写需求成为了一个挑战。

为了解决这一问题,现在的发展趋势包含构建新的 DSL,让重写过程变得简单,或者在编程时直接进行构建。这些方法可以让我们获得有效的梯度,但是仍然需要使用 DSL 或可微分的编程语言进行重写。为了方便开发者,来自 MIT 的研究者开源了 Enzyme。

MegFlow

MegFlow 是旷视天元在 2021 年 9 月份开源的面向计算机视觉应用的流式计算框架,提供了一套可快速完成AI应用部署的视觉解析服务方案。AI应用开发者可以基于MegFlow提供的图像和视频解析服务,最快15分钟即可完成客制化所需功能,例如发票扫描、明火检测等。

常规的 AI 算法交付流程一般分为模型训练、SDK 封装、业务集成和交付验收四个步骤,冗长繁杂。MegFlow总结了旷视内部多年的AI应用工程落地经验,将资源、消息、任务等概念进行了清晰一致的抽象化,将冗长的算法交付流程简化为模型训练、业务集成及交付验收三步。通过 MegFlow ,AI 算法研究人员可以快速将训练好的模型集成部署成简单易用的 AI 服务并完成交付。

MegFlow 的研发团队调研了多种技术方案,最终选择了安全且零额外开销的 Rust 异步生态,从基础上保证了 MegFlow 的安全性与性能。

MegFlow 开源的这四个月里,增加了一些特性,并且还增加了一个使用案例: 猫猫围栏 ,相关视频: 懒出新境界!程序员竟然造出一台人工智能猫粮机! ,实验效果还不错。并且开发者还可以从旷视天元申请免费的算力。

qdrant : 神经网络搜索引擎

qdrant 是一个向量相似性搜索引擎。它提供了一个生产就绪的服务,有一个方便的API来存储、搜索和管理点(带有额外有效payload的向量)。Qdrant是为扩展过滤支持而定制的。这使得它对各种神经网络或基于语义的匹配、分面搜索和其他应用都很有用。基于 Rust 实现,性能也有保证。嵌入神经网络编码器可以变成成熟的应用程序,用于匹配、搜索、推荐等。

目前

其他

还有一些在 2021 年 6月份统计过的依然活跃维护状态的机器学习框架:

  • tch-rs 是Pytorch的Cpp API的Rust绑定,目前正在活跃维护中。
  • ndarray 是一个由Rust官方团队中资深科学计算专家bluss开发的开源项目,实现了基于rust的矩阵和线性运算。目标是在Rust中建立类似于numpy和openblas的科学计算社区。它是机器视觉、数据挖掘、生物信息等多类科学计算库的基础,社区中的主要用户为一些相关技术的高校或者研究所。华为也在深度参与该库的开发。
  • nalgebra ,是 Rust 的通用线性代数库,和 Rapier 一起都是 , Dimforge 开源组织 开发的。
  • tvm-rs 是 TVM 的 Rust 绑定,TVM 是由华盛顿大学在读博士陈天奇等人提出的深度学习自动代码生成方法,去年 8 月 机器之心曾对其进行过简要介绍
  • Neuronika 是一个用 Rust 编写的机器学习框架,与 PyTorch 类似,现已实现最常见的层组件(dense 层、dropout 层等),速度堪比 PyTorch。
  • Whatlang ,基于 Rust 实现的 自然语言 识别项目。

GUI

2021 值得关注的 GUI 项目 : SixtyFPS

SixtyFPS 是一个工具包,可以有效地为任何显示器开发流畅的图形用户界面:嵌入式设备、桌面应用程序、移动端和 Web (目前可编译到 wasm,但仅作为演示,SixtyFPS 无意将 Web 作为主要竞争平台)。它支持多种编程语言,目前是Rust、C++ 或 JavaScript。核心库是 Rust 实现,其他语言的支持通过 C-ABI 来完成。

从2021年开始,就看到一些基于Rust和开源来创业的公司慢慢增加,这个专注于GUI的SixtyFPS也是其中一个,这个开源GUI工具库面向全平台,目标之一是取代Qt,换句话说,SixtyFPS 基本上是大多数 Qt 开发人员都在等待的下一代 QML。

SixtyFPS 两位创始人都对 Qt 开发有深入的经验。其中一位是 曾经在 Qt 公司担任 QtQml 引擎的主要开发人员和维护人员。

看他们的 2021 总结报告,发现他们在2021才注册了公司,和tQCS这样的咨询公司建立了合作关系,找到了第一个客户,招募了新成员。(感觉国外技术流创业跟国内还是有点区别)。tQCS 提供世界No.1的 Qt 咨询和UI/UX设计服务,选择和 SixtyFPS 合作,这意味着什么呢?见仁见智吧。

2022年他们可能要长足支持嵌入式,要有新品牌名字了。

Tauri

Tauri 被看作是 Electron 的替代者,它们都是使用 Web 技术创建桌面应用程序以开发应用程序用户界面的框架。虽然表面看这两者好像都一样,但其实存在很大差别。

下面有一个比较:

Bundle 大小 :tauri 比 electron 小大约 19 倍。

| Framework | OS | Bundle size (installer) | Main executable size | | ------------------- | -------------- | ----------------------- | -------------------- | | Electron 15.3.0 | Windows 11 x64 | 83 MB | 137 MB | | Tauri 1.0.0-beta.10 | Windows 11 x64 | 7MB | 4MB | | Electron 15.3.0 | Linux x64 | 114 MB (deb) | 134 MB | | Tauri 1.0.0-beta.10 | Linux x64 | 6.5 MB (deb) | 16 MB |

内存消耗 : electron 比 tauri 高 9 倍。

| Framework | OS | Number of processes | Total RAM used | | ------------------- | ---------- | ------------------- | -------------- | | Electron 15.3.0 | Windows 11 | 4 | 138 MB | | Tauri 1.0.0-beta.10 | Windows 11 | 8 | 110 MB | | Electron 15.3.0 | Linux x64 | 18 | 224 MB | | Tauri 1.0.0-beta.10 | Linux x64 | 1 | 23 MB |

性能 : tauri 更胜一筹

| Framework | OS | First launch after build | Second launch | | ------------------- | ---------- | ------------------------ | ------------- | | Electron 15.3.0 | Windows 11 | 9940 ms | 1420 ms | | Tauri 1.0.0-beta.10 | Windows 11 | 1230 ms | 1120 ms | | Electron 15.3.0 | Linux x64 | 2570 ms | 1910 ms | | Tauri 1.0.0-beta.10 | Linux x64 | 1560 ms | 1130 ms |

但使用 tauri 的要求更高,tauri API 远不如 Node.JS 完整和充实,所以你在使用 tauri 的时候,有些 API 可能需要自己使用 Rust 去实现它们。

上面的比较来自于: githubhelp.com/Fournux/

另外, Tauri 在 2021 年还孵化出另外两个 crate :

  • wry ,一个跨平台的 WebView 库。
  • tao ,一个跨平台的 Window 库。

Tauri 目前发布了 1.0 beta 版,距离正式稳定版已经不远。 Tauri 选择 Rust 的原因就是为了安全和性能。Tauri 承诺不管你是在 App 中内置 localhost 服务器,还是做其他事情,Tauri 都会为你提供一个安全的底线。将来 Go、Nim、Python、Csharp 等其他后端语言也会被支持,这些都会通过当前这个 Rust 内核提供 C-API 来实现。

Egui

egui 是一款纯 Rust 实现的使用立即模式(immediate mode)的 GUI 框架(在屏幕上实时绘制需要的ui)。在 egui 的 README 中说明了这种立即模式的优缺点,如果你要做选型的话,应该去了解一下。简而言之,立即模式是与保留模式做对比的。立即模式主要优点是应用程序代码变得非常简单,缺点是让布局更加困难,GUI也不能太复杂,否则会给 CPU 带来负担。

Reddit 一位网友 说他们正在使用 Bevy 和 Egui 来构建商业 CAD 软件。

截止目前,egui 发布了 0.16 版本。

其他

  • gtk4-rs ,另一个比较活跃的 GUI 库是 GTK 的 Rust 绑定,2021 年发布了GTK4 的 Rust 绑定 gtk4-rs 0.3.1 版本,目前还在活跃维护中。
  • iced ,一个被 Elm 架构影响的 GUI 框架,它基于 wgpu。也是跨平台的,包括 Web UI。2021 年一直在活跃开发中,但是距离2021年4月份发版的这八个月时间还没有发出新的版本。但它也是被人看好的一个框架。
  • druid ,是一个实验性的 Rust 原生 UI 工具包,值得关注。Druid 目前的发展很大程度上是由它在 Runebender 中的使用而推动的,这是一种新的字体编辑器(处于很早期的阶段)。
  • azul ,是一款跨平台桌面 GUI框架。它将函数式、反应式和面向数据的编程范式与适用于开发跨平台桌面应用程序的 API 混合在一起。Azul 的两个核心原则是不渲染不可见的对象,并使用 DOM 树的组合而不是继承。目前发布了 1.0-alpha版本,距离正式发布 1.0 也不远了。
  • lvgl-rs ,是 LittlevGL 的 Rust 绑定。Littlevgl是一种纯C语言编写的GUI,控件多且美,移植简单,只要对接一个显示接口,需要触摸的再加一个触摸控制接口。

网络与 Web 开发

网络服务

随着世界变得越来越紧密,网络基础设施软件的规模和复杂性正在急剧增加。然而,对该软件的要求与以往一样严格:它不仅必须快速,而且必须“安全”,即能够处理不受信任的数据而不会崩溃或容易受到安全漏洞的攻击。传统上,这两个要求是不一致的:网络程序员必须选择一种既能提供速度又能提供安全性的语言。所以,Rust 是下一代网络基础设施的必须语言。

Tokio

Tokio 是当前 Rust 生态中构建网络服务的中流砥柱,它是一个 Rust 异步运行时和网络应用框架。虽然目前 Rust 生态中也有其他异步运行时,比如 async-std ,但 tokio 无疑是生态最成熟的一个。

Tokio 在安全性、性能和异步任务调度方面都做了很多工作,支持 epoll 和 io_uring ( tokio_uring 刚发布 0.2 版本)。除此之外,还提供 tracing (链路追踪) console (异步调试,刚发布0.1版本) loom(并发测试) 工具。

虽然 Rust 异步特性还需要很大的改进,但是目前因为有 Tokio 的存在,完全可以在生产环境中应用 Rust 异步。

Lunatic

lunatic ,是受 Erlang 影响的一个 WebAssembly 运行时。你可以使用它 快速 健壮 可扩展 的服务器端应用程序,但是你可以通过任意可以编译为 WebAssembly 的语言来使用它。

Lunatic 的并发是基于超轻量级进程,类似于绿色线程或 go-routines 。Lunatic 的进程创建速度快,内存占用小,调度开销低。它们专为 大规模 并发而设计。在一般的应用程序中同时运行数十万个这样的进程并不少见。Lunatic 进程彼此完全隔离,它们有自己的栈、堆甚至系统调用。如果一个进程失败,它不会影响系统的其余部分。这允许开发者创建强大且容错的抽象。

在 Lunatic 上运行的所有进程都被抢占式 异步执行 (基于 smol 实现) 器调度和执行。这使开发者可以自由编写简单的 阻塞 代码,但运行时将确保它在等待 I/O 时实际上不会阻塞线程。

即使在代码中某处存在无限循环,调度也将始终是公平的,不会永久阻塞执行线程。最好的部分是开发者不需要做任何特别的事情来实现这一点,无论你使用哪种编程语言,运行时都会处理它。

这一切都是基于 Rust 和 WebAssembly ( wasmtime 和 wasmtime-wasi) 来实现的,目前只发布了 0.7.0 版本,还在不断高速迭代。

embassy,嵌入式异步运行时

在嵌入式中,通常使用中断、DMA 并利用多核来处理并发事件而不阻塞主循环。这些传统上是通过有意的寄存器写入来处理的。例如,向外围设备发送命令以启动任务,继续运行程序,当任务完成时,会触发一个中断,并立即运行处理完成的代码。Rust 中可以使用基于 Future 的 Async/Await 功能来抽象这些过程。

embassy 是一个旨在让 async/await 成为嵌入式开发的第一选择的项目。异步可以产生更好的性能和更低的功耗,因为执行器不必猜测未来何时准备好执行。但是,程序大小可能比其他替代方案大,这对于内存非常低的某些空间受限设备来说可能是个问题。在 Embassy 支持的设备上,例如 stm32 和 nrf,内存通常足够大,可以容纳适度增加的程序大小。

Embassy 是一个执行器和一个硬件访问层 (HAL)。executor 是一个调度程序,通常执行固定数量的任务,在启动时分配,但以后可以添加更多。HAL 是一种 API,可用于访问外围设备,例如 USART、UART、I2C、SPI、CAN 和 USB。Embassy 在有意义的地方提供异步和阻塞 API 的实现。DMA(直接内存访问)是一个非常适合异步的示例,而 GPIO 状态更适合阻塞 API。

Embassy 还可以提供一个系统计时器,可以将其用于异步和阻塞延迟。在不到一微秒的时间内,应该使用阻塞延迟,因为上下文切换的成本太高,执行器将无法提供准确的定时。

Embassy 目前为多个微控制器系列提供 HAL:

  • embassy-nrf 适用于 Nordic Semiconductor 的 nRF 微控制器
  • embassy-stm32 适用于 ST Microelectronics 的 STM32 微控制器
  • embassy-rp 适用于 Raspberry Pi RP2040 微控制器

Embassy 中的 异步 trait 支持,是未来官方要支持的 Rust async trait 的 MVP 实现案例:

pub trait I2c<A: AddressMode = SevenBitAddress> {
    /// Error type
    type Error;
        // 基于 GAT (nightly Rust)
    type ReadFuture<'a>: Future<Output = Result<(), Self::Error>> + 'a
    where
        Self: 'a;
    fn read<'a>(&'a mut self, addr: A, bs: &'a mut [u8]) -> Self::ReadFuture<'a>;
impl<A: AddressMode = SevenBitAddress> I2c<A> for u8{
      fn read<'a>(&'a mut self, addr: u8, bs: &'a mut [u8]) -> Self::ReadFuture<'a> {
          // 使用 async move