文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

为什么不用Rust?

2024-12-10 16:26

关注

最近我读了一篇批评 Rust 的文章,虽然它提出了一堆好的观点,但我并不认同它 -- 这是一篇容易引起争论的文章。总的来说,我不会推荐一篇批评 Rust 的文章。这是一个遗憾 -- 正视缺点是很重要的,但也需要反对那些草率的或者不准确失误的批判。

所以,下面是我力挺 Rust 的一些理由。

不是所有的开发都是系统编程

Rust 是一种系统编程语言。它提供了对数据布局和代码运行时行为的精确控制,赋予你最大的性能和灵活性。与其他系统编程语言不同的是,它还提供了内存安全--有bug的程序会以一种明确定义的方式终止,而不是出现(潜在的安全威胁)未定义的行为。

然而,在大多数情况下,人们并不需要终极性能或对硬件资源的极致控制。在这种情况下,像 Kotlin 或 Go 这样的现代可管理语言提供了不错的速度和令人羡慕的性能,并且由于使用垃圾回收器进行动态内存管理而保证了内存安全。

复杂度

程序员的时间是宝贵的,如果你选择了 Rust,预计会有一部分时间花在学习各种使用技巧上。Rust 社区倾注了大量的时间来创建各种高质量教程,但 Rust 语言很庞大。即使 Rust 能够为你提供价值,你也可能没有太多精力投入到语言专业知识的提升中。

Rust 提高控制力的代价是选择的魔咒。

  1. struct Foo     { bar: Bar         } 
  2. struct Foo<'a> { bar: &'a Bar     } 
  3. struct Foo<'a> { bar: &'a mut Bar } 
  4. struct Foo     { bar: Box    } 
  5. struct Foo     { bar: Rc     } 
  6. struct Foo     { bar: Arc    } 

在 Kotlin 中,你开始 class Foo(val bar: Bar),就可以继续解决你的业务问题了。在 Rust 中,你需要做出一些选择,有些重要到需要专门的语法。

所有这些复杂性的存在是有原因的 -- 我们不知道如何创建一个更简单的内存安全的低级语言,虽然并不是每个任务都需要用低级语言来解决。

另请参见《为什么C++在瓦萨号沉没时航行》。

https://www.youtube.com/watch?v=ltCgzYcpFUI

编译时间

编译时间是所有工作的倍数。用运行速度较慢但编译速度较快的编程语言编写的代码,可以有机会运行得更快,因为程序员可以有更多的时间去优化代码。

Rust 在通用性的难题中有意挑选了慢速编译器。这并不一定是世界末日(因为由此带来的运行时性能提升是实实在在的),但这确实也意味着在大型项目中,你将不得不为合理的构建时间而拼尽全力。

rustc 实现了可能是生产型编译器中最先进的增量编译算法,但这感觉有点像和语言编译模型打架。

https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html

与 C++ 不同的是,Rust 的构建并不是尴尬的并行,并行的数量受限于依赖图中关键路径的长度。如果你有40多个 core 进行编译,这就会体现出来。

Rust 还缺少一个类似于 pimpl 的功能,这意味着改变一个 crate 需要重新编译(而不仅仅是重新链接)其所有的反向依赖。

pimpl 见: https://en.cppreference.com/w/cpp/language/pimpl

成熟度

只有 5 岁,Rust 绝对是一门年轻的语言。尽管它的前景灿烂,但我曾经在“C将在十年后存在”上下的赌注,要比“Rust 将在十年后存在”下的赌注多得多(参见 Lindy Effect)。如果你写的软件要持续几十年,你应该认真考虑选择新技术的相关风险。但请记住,90年代在银行软件上选择 Java 而不是 Cobol,回想起来,证明是无比正确的选择)。

Lindy Effect: https://en.wikipedia.org/wiki/Lindy_effect

Rust 目前仅有一个完整的实现 -- rustc 编译器。另一个最好的替代实现 mrustc,故意省略了许多静态安全检查。rustc 目前只支持一个生产就绪的后端 -- LLVM。因此,它对 CPU 架构的支持比 C 窄,C 架构有 GCC 实现,也有许多厂商特定的专有编译器。

最后,Rust 缺乏官方规范。参考文档是一个正在进行中的工作,还没有记录所有细致的实现细节。

可替代性

在系统编程领域,除了 Rust 之外,还有一些其他语言,主要有 C、C++ 和 Ada。

现代 C++ 提供了提高安全性的工具和准则。甚至有人提议建立类似 Rust 的生命周期机制。与 Rust 不同,使用这些工具并不能保证没有内存安全问题。然而,如果你已经维护了大量的 C++ 代码,那么检查一下遵循最佳实践和使用 sanitizer, 对于解决安全问题是有意义的。这很难,但显然比用另一种语言重写更容易。

如果你使用 C 语言,你可以使用形式化方法来证明没有未定义的行为,否则你只能详尽地测试一切。

Ada 是内存安全的,如果你不使用动态内存(永远不调用 free)。

Rust 是成本/安全曲线上的一个有趣的点,但肯定不是唯一的一个点。

工具

Rust 工具是值得称赞的东西。基线工具、编译器和构建系统(cargo),经常被认为是一流的。

但是,举例来说,一些与运行时相关的工具(最明显的是堆分析)目前还不存在 -- 如果没有运行时工具,就很难对程序运行时进行分析。此外,虽然 IDE 的支持还算不错,但远没有达到 Java 级别的可靠性。如今在 Rust 中,数百万行程序的自动复杂重构还做不到。

集成

不管 Rust 的愿景是什么,今天的系统编程世界还是 C 和 C++ 的天下,这是一个事实。Rust 有意不试图模仿这些语言 —— 它没有使用 C++ 风格的类或 C ABI。

这意味着,它们之间的集成需要明确的桥梁。这些都不是无缝的。它们是不安全的,并不总是零成本的,并且需要在语言之间同步。虽然片断式集成的一般也还能维持,工具也能赶上,但一路上却意外的复杂。

一个具体的小麻烦是,Cargo 独特的世界观(这对纯 Rust 项目来说是个福音)可能会使它更难与更大的构建系统集成。

性能

"使用LLVM" 并不是解决所有性能问题的通用方案。虽然我不知道 C++ 和 Rust 在规模上的性能的基准,但不难列出一个 Rust 不如 C++ 一些性能问题列表。

最大的一个可能是 Rust 的 move 语义是基于 value 的(机器代码级别的 memcpy)。相比之下,C++ 语义使用的是你可以使用数据的特殊引用(机器代码级的指针)。理论上,编译器应该能够看穿复制链,但在实践中往往不能。#57077. 一个相关的问题是没有放置 new -- Rust 有时需要从堆栈中复制字节,而 C++ 可以在原地构造东西。

57077 https://github.com/rust-lang/rust/issues/57077

有点有趣的是,Rust 的默认 ABI(为了使其尽可能高效,它并不稳定)有时比 C 更差。#26494.

https://github.com/rust-lang/rust/issues/26494#issuecomment-619506345

最后,虽然理论上 Rust 代码应该更高效,因为有更丰富的别名信息,但启用别名相关的优化会引发 LLVM bug 和误编译。#54878.

https://github.com/rust-lang/rust/issues/54878

但是,重申一下,这些都是挑出来的例子,有时候这些领域会有相反的情况。例如,std::unique_ptr 的性能问题在 Rust 的 Box 中就不存在。

一个潜在的更大的问题是,Rust 的定义时间检查的泛型,表现力不如 C++。所以,一些高性能的 C++ 模板技巧,在 Rust 中就很难用漂亮的语法来表达。

模板技巧 http://eigen.tuxfamily.org/index.php?title=Expression_templates

Unsafe 的定义

一个比所有权和借用更核心的问题也许是 unsafe 的边界。通过在 unsafe 的块和函数后面划定所有危险的操作,并为它们提供安全的上层接口,就有可能创建一个既是:

很明显,这个承诺在实践中得到了验证:有问题的 Rust 代码会带来 panic,而不是缓冲区超限。

但在理论上来看,问题就不那么乐观了。

首先,没有 Rust 内存模型的定义,所以无法正式检查给定的不安全块是否有效。有非正式的 "rustc 所做的或可能依赖的事情 "的定义,并且在进行中的运行时验证器,但实际的模型是在变化的。所以可能有一些不安全的代码,今天在实践中还可以用,明天可能就被宣布无效,明年又被新的编译器优化打破。

其次,还有一个观察,不安全块其实不是模块化的。足够强大的不安全块实际上可以扩展语言。两种这样的扩展单独使用可能是好的,但如果同时使用会导致未定义的行为,观测等价性和不安全代码。

见: https://smallcultfollowing.com/babysteps/blog/2016/10/02/observational-equivalence-and-unsafe-code/

最后,编译器中存在 bug。

见:https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3A%22I-unsound+%F0%9F%92%A5%22

下面是我刻意忽略的一些东西。

英文原文:

https://matklad.github.io/2020/09/20/why-not-rust.html

本文转载自微信公众号「高可用架构」,可以通过以下二维码关注。转载本文请联系高可用架构公众号。

 

来源: 高可用架构内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯