《我看到的 Rust 历史》
Rust 语言最近相当火热,被很多人认为是会在未来取代 C/C++ 的语言。好像是个公司就得用 Rust 做“后端”,没有其它选择了一样。这不得不让我想起 Rust 最早时候的历史,以及最近我发现的 Rust 语言的严重设计问题。
2009 年我还在 IU 的时候,有两个半路出家的同学,本科都不是计算机专业的,在 Dan Friedman 的课上完全迷糊,痛苦不堪那种。每每在课上讲自己对于 Friedman 给的“脑筋转弯题”的结果,我也在场的时候,他们声音都是发颤的,因为他们一本正经好像自己很懂,却又怕被我问出破绽来。他们也声称做出过 CPSer,最后给出的结果却是错的。仔细观察,我发现他们根本不理解里面的原理,只是做了个“样子”,像有那么回事而已。
然而这样的人确实很会拍胸脯,会把握关键词,时机和人际关系。所以后来暑假结束时,我忽然收到通知,他们要给大家做一个关于“Rust 语言”的讲座。原来那个暑假,他们两个去了 Mozilla 实习,项目就是开发 Rust 语言。那就是我第一次听说 Rust 语言。
然而他们做的这个 Rust 的演讲却空洞无物,全是大口号。他们的幻灯片上画了一个大三角形,提出 Rust 的”三大特色“,当然其中包括了”安全“(security),另外两个我不记得了。当时,他们号称 Rust 使用静态分析,实现了完全没有 GC(垃圾回收)的内存管理。整个讲座就像是商业宣传,没有任何实质的技术内容,全是口号。
“完全没有 GC,静态的内存管理”,这其实是我那时候最感兴趣的话题。我也不满意 Java 等语言的 GC 带来的“随机停顿”,所以我花了很多时间来琢磨内存管理应该如何设计,可以“完全依靠静态分析”,不需要任何动态的垃圾回收。这个理想,就像 Rust 当时所号称的那样。
我琢磨了一段时间,实验了各种内存模型和静态分析。然而最后,这一切的梦想都被 Kent Dybvig 的一句话打破了。我还记得,我在 Kent 的办公室里说:“我想实现这么一个完全依靠静态分析,不用 GC 管理内存的语言。”结果他冷静地说:“完全静态的内存管理,这可能吗?内存管理本来就是一个动态过程。“
听了这话,我才开始反省之前的理想。我重新分析了编程语言的内存模型,发现它确实是一个”不可计算“的动态过程,等价于”停机问题“。这么简单的道理,我为什么没想到呢?
我又提出,也许应该使用引用计数进行内存回收,这样就不会有 GC 的随机停顿了。Kent 又告诉我,引用计数是有比较大开销的,很多时候还不如 GC,使用 GC 根本就不是问题,主要看你怎么实现它。
看来我思考过的一切,Kent 都已经思考或者经历过了,毕竟他开发编译器已经超过 30 年之久。我不得不佩服他的 Chez Scheme 编译器,它不但具有闪电般的编译速度,而且有合理的 GC 设计。它的垃圾回收器不但效率高,而且是可以让用户自己配置的。如果 GC 出现长时间停顿,用户可以通过调整参数改变它的行为。
Chez Scheme 为什么编译速度这么快?Kent 的回答是:因为它不做那些针对“愚蠢代码”的优化,它假设程序员有基本的素养,只做程序员自己没法做的高级优化。
Chez Scheme 这一切优势,都来自于设计的智慧,而不只是“聪明”和蛮干。
然而看看现在的 Rust 呢?很显然,当年的“完全静态分析”实现内存管理的理想已经破灭,Rust 也需要使用引用计数(Rc,Arc)。就像 Kent 说的,完全静态的内存管理是不可能的。
而且 Rust 还有“unsafe 代码”,因为已有的静态分析造成的限制,让它无法写出所有需要的代码,所以很多时候不得不跳出安全机制,使用“unsafe”关键字,使用没有静态安全保证的代码。最新的研究,有一些就是针对这些 unsafe 区域的,什么 Stack Borrow,Tree Borrow 等概念。然而它们做的其实是加入一些限制,结果你又没法写出应该可以表达的代码了。
然而即使一再地后退,又有引用计数,又有 unsafe,Rust 社区却仍然坚持使用“完全静态保证”这样的广告词。如果你指出这些例外情况,他们就改口说:这是 Rust 的哲学。
Rust 社区的“静态保证”口号传播如此广泛,如果你有异议,练刚入门的新手都会来“教育”你。甚至不需要人来教育你,如果你跟 ChatGPT 说这事,它都会跟你说:你不懂,这是 Rust 的哲学!
”哲学“?好一个高大的词汇。也就是说,这是一个“理想”或者希望做到的事情,一直没有做到,而且把事情越搞越复杂。
这就是为什么我虽然完全理解 Rust 的所谓“借用”,“生命周期”等概念,现在又有了 AI 工具可以帮我折腾,却一直不用 Rust。我不相信 Rust 真的是可以取代 C/C++ 的语言。
在“计算机科学基础班第5期”教会了大家 Rust 的内存管理机制之后,我更加欣赏 C 和 C++ 了。如果真有需要高性能的场合,我会选择 C/C++ 而不是 Rust。