当前位置: 首页 > 科技观察

为什么不生锈?

时间:2023-03-16 00:45:29 科技观察

我最近读了一篇对Rust的评论,虽然它提出了很多好的观点,但我不同意它——这是一个有争议的评论。总的来说,我不会推荐一篇批评Rust的文章。遗憾的是——重要的是要正视缺点,但也要反驳草率或不准确的批评。所以,这是我支持Rust的一些理由。并非所有的开发都是系统编程Rust是一种系统编程语言。它提供对数据布局和代码运行时行为的精确控制,为您提供最大的性能和灵活性。与其他系统编程语言不同,它还提供内存安全性——有缺陷的程序以明确定义的方式终止,而不是表现出(可能威胁安全的)未定义行为。然而,在大多数情况下,不需要终极性能或对硬件资源的极端控制。在这种情况下,像Kotlin或Go这样的现代可管理语言提供了不错的速度和令人羡慕的性能,并且由于使用垃圾收集器进行动态内存管理而保证了内存安全。ComplexityProgrammer的时间是宝贵的,如果你选择Rust,期望花一些时间学习各种使用技巧。Rust社区投入了大量时间来创建各种高质量的教程,但Rust语言非常庞大。即使Rust可以为你提供价值,你也可能没有太多精力投入到提高你的语言专业知识上。Rust增强控制的代价是选择的魅力。structFoo{bar:Bar}structFoo<'a>{bar:&'aBar}structFoo<'a>{bar:&'amutBar}structFoo{bar:Box}structFoo{bar:Rc}structFoo{bar:Arc}在Kotlin中,您启动classFoo(valbar: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个以上的内核编译,这将显示出来。Rust还缺少类似pimpl的功能,这意味着更改crate需要重新编译(不仅仅是重新链接)它的所有反向依赖项。pimpl参见:https://en.cppreference.com/w/cpp/language/pimpl成熟度只有5岁,Rust绝对是一门年轻的语言。尽管有承诺,但我对“C将在十年内存在”的赌注远多于对“Rust将在十年内存在”的赌注(参见林迪效应)。如果您编写的软件可以使用数十年,您应该认真考虑与选择新技术相关的风险。但请记住,回想起来,在90年代选择Java而不是Cobol作为银行软件是正确的选择)。LindyEffect:https://en.wikipedia.org/wiki/Lindy_effectRust目前只有一个完整的实现——rustc编译器。另一个最佳替代实现mrustc故意省略了许多静态安全检查。rustc目前仅支持一种生产就绪后端——LLVM。因此,与具有GCC实现的C以及许多供应商特定的专有编译器相比,它对CPU体系结构的支持范围更窄。最后,Rust缺乏官??方规范。参考文档是一项正在进行的工作,尚未记录实施的所有细节。可替代性在系统编程领域,除了Rust,还有一些其他的语言,主要是C、C++和Ada。现代C++提供了提高安全性的工具和指南。甚至还有类似Rust的生命周期机制的提议。与Rust不同,不能保证使用这些工具不会出现内存安全问题。但是,如果您已经维护了大量C++代码,那么检查遵循最佳实践和使用消毒剂是否有助于解决安全问题是有意义的。这很难,但显然比用另一种语言重写它更容易。如果用C,可以用形式化的方法来证明不存在未定义的行为,否则只能穷举一切。如果您不使用动态内存(永远不要调用free),Ada是内存安全的。Rust是成本/安全曲线上一个有趣的点,但肯定不是唯一的一点。工具Rust工具值得赞赏。基准工具、编译器和构建系统(货物),通常被认为是一流的。但是,例如,一些与运行时相关的工具(最著名的是堆分析)目前并不存在——如果没有运行时工具,就很难分析程序的运行时。此外,虽然IDE支持不错,但它远不及Java级别的可靠性。今天的Rust不可能对数百万行程序进行自动复杂重构。集成不管Rust的愿景如何,当今的系统编程世界由C和C++主导是事实。Rust有意不尝试模仿那些语言——它不使用C++风格的类或CABI。这意味着它们之间的集成需要清晰的桥梁。这一切都不是天衣无缝的。它们不安全,并不总是免费的,并且需要语言之间的同步。碎片化的整合虽然大体上还能维持,工具也能赶上,但一路走来却出乎意料的复杂。一个具体的问题是Cargo独特的世界观(这对纯Rust项目来说是一个福音)可能会使其更难与更大的构建系统集成。性能“使用LLVM”并不是所有性能问题的通用解决方案。虽然我不知道C++和Rust大规模性能的基准,但不难列出一些Rust不如C++的性能问题。最大的一个可能是Rust的移动语义是基于值的(机器代码级别的memcpy)。相比之下,C++语义使用特殊引用(机器代码级别的指针),您可以在其中处理数据。理论上,编译器应该能够看穿复制链,但在实践中他们往往做不到。#57077。一个相关的问题是不放置新的——Rust有时需要从堆栈复制字节,而C++可以就地构造东西。57077https://github.com/rust-lang/rust/issues/57077有趣的是,Rust的默认ABI(为了使其尽可能高效而不稳定)有时比C更差。#26494。https://github.com/rust-lang/rust/issues/26494#issuecomment-619506345最后,虽然理论上Rust代码应该由于更丰富的别名信息而更高效,但启用与别名相关的优化会导致LLVM错误和编译错误。#54878.https://github.com/rust-lang/rust/issues/54878但是,重申一下,这些都是单个示例,有时在这些领域中会发生相反的情况。例如,std::unique_ptr的性能问题在Rust'sBox中不存在。一个潜在的更大问题是Rust的定义时间检查泛型不像C++那样具有表现力。因此,一些高性能的C++模板技巧在Rust中很难用漂亮的语法表达。模板技巧http://eigen.tuxfamily.org/index.php?title=Expression_templatesUnsafe定义比所有权和借用更核心的问题可能是不安全的边界。通过在不安全的块和函数后面划定所有危险操作,并为它们提供安全的上层接口,可以创建一个兼具:合理(非不安全代码不能导致未定义行为)的代码。和模块化(不同的不安全块可以单独检查)。显然,这一承诺已在实践中得到证实:有缺陷的Rust代码会panic,而不是缓冲区溢出。但从理论上讲,问题并没有那么乐观。首先,Rust的内存模型没有定义,因此无法正式检查给定的不安全块是否有效。有“rustc做什么或可能依赖什么”的非正式定义,运行时验证器正在进行中,但实际模型在不断变化。所以可能有一些不安全的代码今天在实践中仍然可用,明天可能被宣布无效,明年被新的编译器优化破坏。其次,也是另一个观察结果,不安全块实际上并不是模块化的。足够强大的不安全块实际上可以扩展语言。单独使用两个这样的扩展可能没问题,但如果一起使用,可能会导致未定义的行为、观察到的等价性和不安全的代码。请参阅:https://smallcultfollowing.com/babysteps/blog/2016/10/02/observational-equivalence-and-unsafe-code/最后,编译器中存在一个错误。参见:https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3A%22I-unsound+%F0%9F%92%A5%22下面是我的故意忽略一些事情。经济学:(“招聘Rust程序员很难”)——我认为“成熟度”部分抓住了它的本质,不能将其简化为先有鸡还是先有蛋的问题。依赖项:(“stdlib太小/对所有内容的依赖项太多”)——考虑到Cargo和语言的相关部分有多好,我个人不认为这是一个问题。动态链接:(“Rust应该有一个稳定的ABI”)——我不认为这是一个强有力的论据。单态化从根本上与动态链接不兼容,如果确实需要,可以使用CABI。我确实认为这里有改进的空间,但我认为改进不需要特定于Rust。参见:https://internals.rust-lang.org/t/a-stable-modular-abi-for-rust/12347/10?u=matklad英文原文:https://matklad.github.io/2020/09/20/why-not-rust.html本文转载自微信公众号《高可用架构》,可通过以下二维码关注。转载本文请联系高可用架构公众号。