0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

用Rust重写了自己的项目

jf_wN0SrCdH 来源:Rust语言中文社区 2023-02-02 16:45 次阅读

前言

Rust 已经悄然成为了最受欢迎的编程语言之一。作为一门新兴底层系统语言,Rust 拥有着内存安全性机制、接近于 C/C++ 语言的性能优势、出色的开发者社区和体验出色的文档、工具链和IDE 等诸多特点。本文将介绍笔者使用 Rust 重写项目并逐步落地生产环境的过程,以及在重写过程选择 Rust 的原因、遇到的问题以及使用 Rust 重写带来的成果。

我们目前正在使用 Rust 开发的项目叫做 KCL,目前全部实现代码已经在 Github 上开源。KCL 是一个基于约束的记录及函数领域编程语言,致力于通过成熟的编程语言技术和实践来改进特领域如云原生 Kubernetes 领域的大量繁杂配置编写和安全策略校验等,致力于构建围绕配置的更好的模块化、扩展性和稳定性,更简单的逻辑编写,以及更快的自动化集成和良好的生态延展性。更具体的 KCL 使用场景请访问 KCL 网站,本文中不再过多赘述。

KCL 之前是使用 Python 编写的,出于用户使用体验、性能和稳定性的考虑,决定用 Rust 语言进行重写,并获得了以下好处:

1.更少的 Bug,源于 Rust 强大的编译检查和错误处理方式

2. 语言端到端编译执行性能提升了66%

3. 语言前端解析器性能提升了20 倍

4. 语言中端语义分析器性能提升了40 倍

5. 语言编译器编译过程平均内存使用量变为原来 Python 版本的一半

我们遇到了什么问题

就像社区中同类型项目 deno, swc, turbopack, rustc 等编译器、构建系统或者运行时在技术上使用 Rust 做的事情类似,我们使用 Rust 完整构建了编译器的前中端和运行时,取得了一定的阶段性成果,但是我们大约在一年前并不是这个样子的。

一年前,我们使用 Python 语言构建了整个 KCL 语言编译器的实现,虽然在一开始的时候运行良好,Python 简单易上手,生态丰富,团队的研发效率也很高,但是随着代码库的扩张和工程师人数的增加,代码维护起来愈加困难。

尽管我们在项目中强制编写 Python 类型注解,采用更严格的 lint 工具,代码测试行覆盖率也达到了 90% 以上,但是仍然会出现很多诸如 Python None 空对象,属性未找到等运行时才会出现错误,并且重构 Python 代码时也需要小心翼翼,反应到 KCL 语言上就是一个接一个的 bug, 严重影响用户使用体验。

此外,当 KCL 使用对象是广大开发者用户时,编程语言或者说编译器内部实现出现任何错误都是不可容忍的,这些也给我们的用户使用体验带来了一系列问题,使用 Python 编写的程序启动速度较慢,性能无法满足自动化系统在线编译和执行的效率诉求,因为在我们的场景中,用户修改 KCL 代码后需要能很快的展示编译结果,显然使用 Python 编写的编译器并不能很好地满足使用需求。

为什么选择 Rust

笔者所在团队基于如下原因选择了 Rust

1. 使用 Go, Python, Rust 三种语言实现了简单的编程语言栈式虚拟机并作了性能对比,Go 和 Rust 在这个场景下性能接近,Python 有较大性能差距,综合考虑下采用了 Rust,具体三种语言实现的栈式虚拟机代码细节在https://github.com/Peefy/StackMachine,感兴趣的同学可以前往浏览

2. 越来越多的编程语言的编译器或运行时特别是前端基础设施项目采用 Rust 编写或重构,此外基础设施层,数据库、搜索引擎、网络设施、云原生、UI 层和嵌入式等领域都有 Rust 的出现,至少在编程语言领域实现方面经过了可行性和稳定性验证

3. 考虑到后续的项目发展会涉及区块链智能合约方向,而社区中大量的区块链和智能合约项目采用 Rust 编写

4. 通过 Rust 获得更好的性能和稳定性,让系统更容易维护、更加健壮的同时,可以通过 FFI 暴露 C API 供多语言使用和扩展,方便生态扩展与集成

5. Rust 对 WASM 的支持比较友好,社区中大量 WASM 生态是由 Rust 构建,KCL 语言和编译器可以借助 Rust 编译到 WASM 并在浏览器中运行

基于以上原因综合考虑选择了 Rust 而不是 Go 等其他语言,整个重写过程下来发现 Rust 综合素质确实过硬(第一梯队的性能,足够的抽象程度),虽然在一些语言特性特别是生命周期等上手成本有一些,生态上还不够丰富。

总之编程语言可以做的事情,Rust 均可以做,具体可能还是要根据具体的场景和问题来做选择。同时如果想要使用好 Rust, 还需要深入理解内存、堆栈、引用、变量作用域等这些其它高级语言往往不会深入接触的内容。

使用 Rust 过程中遇到了哪些困难

虽然决定了使用 Rust 重写整个 KCL 项目,其实团队成员大部分成员是没有使用 Rust 编写一定代码体量项目的经验,包括笔者个人自己也仅仅学习过《The Rust Programming Language》中的部分内容,依稀记得学习到Rc和RefCell等智能指针内容就放弃了,那时没想到 Rust 中还能有与 C++ 中类似的东西。

使用 Rust 前预估的风险主要是 Rust 语言接触和学习的成本,这个确实在各种 Rust 的文章博客中均有提到,因为 KCL 项目整体架构并未发生太大变化,只是部分模块设计和代码编写针对 Rust 作了优化,因此整个重写是在边学边实践中进行。确实在刚开始使用 Rust 编写整个项目的时候花费在知识查询、编译排错的时间还是很多的,不过随着项目的进行渐入佳境,笔者个人经验使用 Rust 遇到的困难主要是心智转换和开发效率两方面:

心智转换

首先 Rust 的语法语义很好地吸收和融合了函数式编程中类型系统相关的概念,比如抽象代数类型 ADT 等,并且 Rust 中并无“继承”等相关概念,如果不能很好地理解甚至连其他语言中稀松平常的结构定义在 Rust 中可能都需要花费不少时间,比如如下的 Python 代码可能在 Rust 中的定义是这个样子的

Python

5584b528-a28e-11ed-bfe3-dac502259ad0.png

Rust

5594d700-a28e-11ed-bfe3-dac502259ad0.png

当然更多的时间是在与 Rust 编译器本身的报错作斗争,Rust 编译器会经常使开发人员"碰壁",比如借用检查报错等,特别是对于编译器来讲,它处理的核心结构是抽象语法树 AST,这是一个递归和嵌套的树结构,在 Rust 中有时很难兼顾变量可变性与借用检查的关系,就如 KCL 编译器作用域Scope的结构定义结构那样,对于存在循环引用的场景,用于需要显示意识到数据的相互依赖关系,而大量使用Rc,RefCell和Weak等 Rust 中常用的智能指针结构

55a72536-a28e-11ed-bfe3-dac502259ad0.png

开发效率

Rust 的开发效率可以用先抑后扬来形容。在刚开始上手写项目时,如果团队成员没有接触过函数式编程相关概念以及相关的编程习惯,开发速度将显著慢于 Python、Go 和 Java 等语言,不过一旦开始熟悉 Rust 标准库常用的方法、最佳实践以及常见 Rust 编译器报错修改,开发效率将大幅提升,并且原生就能写出高质量、安全、高效的代码。

比如笔者个人当初遇到一个如下代码所示的与生命周期错误前前后后排查了很久的时间才发现原来是忘记标注生命参数导致生命周期不匹配。此外 Rust 的生命周期与类型系统、作用域、所有权、借用检查等概念耦合在一起,导致了较高的理解成本和复杂度,且报错信息往往不像类型错误那么明显,生命周期不匹配错误报错信息有时也略显呆板,可能会导致较高的排错成本,当然熟悉相关概念写多了之后效率会提高不少。

55cf9106-a28e-11ed-bfe3-dac502259ad0.png

使用 Rust 重写收益比

经过团队几个人花费几个月时间使用 Rust 完全重写并稳定落地生产环境几个月后,回顾整个过程感觉这件事情的收获非常大。

从技术角度层面来看,重写的过程不仅仅锻炼了快速学习一门新的编程语言、编程知识并将其付诸实践,并且整个重写过程让我们又反思了 KCL 编译器中设计不合理的部分并进行修改,对一个编程语言而言,这是一个长周期的项目,我们收获的是编译器系统更加稳定、安全,且代码清晰,bug 更少、性能更好的技术产品服务于用户,虽然没有全部模块得到高达 40 倍的性能,因为部分模块如 KCL 运行时的性能瓶颈在于内存深拷贝操作,但笔者个人认为仍然是值得的。且当 Rust 使用时间到达一定时长后,心智和开发效率不再是限制因素,就像学车那样,拿到驾照后更多是上路实践和总结。

结语

笔者个人觉得使用 Rust 重写项目后最重要的是不是我学会了一门新的编程语言,也不是 Rust 很流行很火因此我们在项目中采用一下,或者使用 Rust 编写了多少炫技的代码,是真真正正地使得语言和编译器本身更加稳定,能够在生产环境平稳落地并长期使用,启动速度和自动化效率不再受困扰,性能优于社区其他同类型领域编程语言,使我们语言和工具的用户感受到体验提升,这些都得益于 Rust 的无 GC、高性能、更好的错误处理内存管理、零抽象等特性。

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程语言
    +关注

    关注

    9

    文章

    1892

    浏览量

    33778
  • 编译器
    +关注

    关注

    1

    文章

    1586

    浏览量

    48795
  • Rust
    +关注

    关注

    1

    文章

    225

    浏览量

    6441

原文标题:性能提升 40 倍!我们用 Rust 重写了自己的项目

文章出处:【微信号:Rust语言中文社区,微信公众号:Rust语言中文社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    只会用Python?教你在树莓派上开始使用Rust

    结合起来,并在Raspberry Pi上安装Rust。设置Raspberry Pi对于此项目,您将需要:Raspberry PiLED。220-1k欧姆电阻。面包板和接线。使用GPIO 18连接到LED
    发表于 05-20 08:00

    使用rust开发stm32系列教程

    本文为使用 rust 开发 stm32 系列教程前言。Why RustRust 特性就不用多介绍了,有个编译器管着有时候比C到处浪把自己整没了好。ST官方逐渐停止对C固件库的更新,使用MX感觉没
    发表于 08-20 07:18

    怎样去使用Rust进行嵌入式编程呢

    使用Rust进行嵌入式编程Use Rust for embedded development篇首语:Rust的高性能、可靠性和生产力使其适合于嵌入式系统。在过去的几年里,Rust在程序
    发表于 12-22 07:20

    如何利用C语言去调用rust静态库呢

    持续。rust整个结构还不是特别清晰,特别是库和wrapper相关的同个C项目,包含多个rust的静态库,静态库中也会有符号冲突这点应该可以把多个rust程序打包一个库来解决。能否准确
    发表于 06-21 10:27

    如何在STM32 (Cortex M3)和GD32(RISC-V)上Rust开发

    RUST HAL 实现刚好是华科本科生写的,恰好我也是华科的研究生,太巧了 ;)所以 rust 开发嵌入式不需要重复实现相同的功能,使用开源的 crate 软件包就可以了。比如我们先下载下来
    发表于 06-21 10:38

    Rust代码中加载静态库时,出现错误 ` rust-lld: error: undefined symbol: malloc `怎么解决?

    “ [i]malloc ”、“ [i]exit ”。我验证了使用 ` [i]nm ` 命令。 问题是我打算使用 ffi 在 rust 中使用这个静态库。当我尝试在我的 Rust 代码中加载静态库
    发表于 06-09 08:44

    微软开发基于Rust的新编程语言,将很快开源

    此前,微软表示正探索将Rust作为C和C++的安全替代方案,并且也对外展示了使用Rust重写Windows组件的体验,根据微软的说法,Rust是一种从根本上考虑安全性的编程语言,他们将
    的头像 发表于 12-03 10:36 3776次阅读

    Google在Chromium项目中支持使用Rust

    Rust 1.66.1 发布 Rust 1.66.1 修复了 Cargo 在使用 SSH 克隆依赖项或注册表索引时不验证 SSH 主机密钥的问题。此安全漏洞被跟踪为 CVE-2022-46176
    的头像 发表于 01-16 10:52 1337次阅读

    Cloudflare用Rust重写Nginx C模块,构建没有Nginx的未来

    近日,Cloudflare 工程师介绍了如何使用 Rust 重写基于 C 语言的 Nginx 模块。Cloudflare 工程师在博客写道,他们用 Rust 为 Cloudflare 基础设施中最
    的头像 发表于 03-08 09:36 539次阅读

    一个用Rust开发的压测工具rsb

    一个用 Rust 开发的压测工具,项目地址:rsb,给个 star 鼓励下。
    的头像 发表于 03-21 09:32 632次阅读

    Rust重写的LSP:KCL IDE 插件的功能介绍与设计解析

    在这次更新中,我们发布了全新的 KCL VS Code 插件,并且用 Rust 重写了 LSP 的 Server 端。我们提供了 IDE 中常用的代码辅助功能,如高亮、跳转、补全、Outline、悬停、错误提示等。
    的头像 发表于 05-11 09:39 723次阅读
    <b class='flag-5'>Rust</b><b class='flag-5'>重写</b>的LSP:KCL IDE 插件的功能介绍与设计解析

    Windows 11初尝Rust,36000行内核代码已重写

    更早些时候,微软用 Rust 重写了 DirectWrite Core 库的概念验证,它是 Windows 的 DWrite 引擎的 Windows App SDK 实现,用于文本分析、布局和渲染
    的头像 发表于 05-19 16:39 746次阅读
    Windows 11初尝<b class='flag-5'>Rust</b>,36000行内核代码已<b class='flag-5'>重写</b>!

    如何在Rust项目中使用InfluxDB 2.x

    了更好的性能和更好的用户体验。Rust语言提供了InfluxDB 2.x的官方客户端库,可以方便地在Rust项目中使用InfluxDB 2.x。 本教程将介绍如何在Rust
    的头像 发表于 09-19 16:33 458次阅读

    Rust重写基础软件的实践代码

    项目转化过程中我遇到了一个与 CAS (Compare and Swap) [2] 操作实现相关的问题,在计算机科学中CAS 是多线程/协程中用于实现同步的原子指令。
    的头像 发表于 01-19 10:05 286次阅读

    一次Rust重写基础软件的实践

    受到2022年“谷歌使用Rust重写Android系统且所有Rust代码的内存安全漏洞为零” [1] 的启发,最近笔者怀着浓厚的兴趣也顺应Rust 的潮流,尝试着将一款C语言开发的基础
    的头像 发表于 01-25 11:21 347次阅读