写了50+万行代码、创办两家公司,他押注Rust十年后:“Rust工程师的平均水平,比大多数语言都要高”
仅用于站内搜索,没有排版格式,具体信息请跳转上方微信公众号内链接
【CSDN编者按】十年前,Rust还只是少数程序员眼中的希望之光;十年后,它已成为现代编程语言中的佼佼者。本文作者是Rust的早期拥护者之一,他以十年的实践经历,回顾了Rust如何从一个用起来很“痛苦”的项目,成长为如今具备强大工具链、卓越开发体验和跨领域潜力的主流语言。
原文链接:https ://tably. com/tably/10-years-of-betting-on-rust
作者|AlecMocatta翻译|郑丽媛
出品|CSDN(ID:CSDNnews)
2015年6月,我写下了人生中第一行Rust代码——那是在Rust1. 0正式发布后的一个月。彼时,我刚从C、Python和JavaScript转到Rust,谁料自此再未回头。
在创办了两家基于Rust的初创公司、写过50+万行Rust代码之后,我想借这个时间节点聊聊我的心得与对Rust未来的展望。
初期很“痛”
回顾最初的日子,那时Rust兼容性真是一言难尽——不仅是crates(Rust的第三方库)之间兼容性差,连与编译器本身的兼容性也问题频出。光是一个简单的bug修复可能就需要升级编译器,而这又会引发像syntex(曾是serde的核心依赖)这样不稳定的crate升级,然后连带着影响一堆下游依赖。
所以,我们常常不得不“更新整个世界”来适配关键的修复或新特性。在早期,这几乎是每六周一次的固定动作——我们要跟着编译器发布的节奏走。于是,大量时间都花在了“二分查找兼容版本组合”这件事上,团队非常低效。
对我来说,“和Rust的借用检查器斗智斗勇”这件事绝不是梗,是真的。得益于我在C++、Java和Objective-C方面的经验,Rust的trait概念上手还算轻松。但生命周期以及那些不会实际影响代码生成、却又必须“证明正确”的逻辑,确实花了我一番功夫才理解。所幸,我有一些非常耐心的朋友和同事,帮了不少忙。
后来,随着代码库和团队逐渐扩张,编译时间也变得越来越难以忍受。大型类型频频成为性能瓶颈(现在偶尔也还是),需要费心分析并做出优化。虽然我们也做了一些投入把编译时间压下来,但这还是拖慢了迭代速度,想要快速做原型也变得需要不少准备工作。
Rust社区很不错
Rust社区一直以来都聚集着非常“有品位”的程序员。我所说的这种品位体现在:依赖库构建过程简洁、实现优雅、运行高效且稳定。相比之下,我每次换回TypeScript或Python都会感到有些“失望”——这也是Rust连续九年稳居“最受欢迎编程语言”榜首的原因之一吧!
如果要具体说“Rust为什么成功”,可以单独写一篇长文,但我认为主要核心在于:社区中那一批有原则、有判断、非常认真负责的开发者们。他们擅长说“不”与“还不到时候”,而正是这种坚持让生态慢慢走上了正轨。
作为一家公司的创始人,我也深切感受到了这种文化的红利。我们是伦敦为数不多使用Rust的公司之一,吸引了不少希望用自己最喜欢的编程语言工作的优秀工程师。我说实话,一名Rust工程师的平均水平,确实比大多数其他编程语言的平均值要高不少。
Rust已成为一种安全的选择
在最早期,选择Rust通常意味着你要不断做些边边角角的底层工作。比如std(标准库)当时缺少一些功能,我们就自己搞了一个功能补丁库:里面塞满了workaround(替代方案)、hack(变通实现)和各种扩展。这些代码虽然让业务逻辑更清晰、运行更快,但并不适合提PR回标准库,或者说,在当时根本不可能被接受。
但慢慢地,我们发现这个库几乎不再需要新增功能,甚至在逐渐删除旧内容——我们自定义的实现终于可以“功成身退”。如今,哪怕是标准库中那些相对冷门或者抽象的功能,其实现也往往存在且高效,令人欣慰。
总体来说,现在的Rust整体体验早已进入稳定区间:构建和升级过程高度可预测,几乎不再依赖非Rust组件;编译期、代码生成和内联爆炸等“惊喜”基本绝迹;生态对semver(语义化版本)的遵守也更加严格;推理系统的改进让借用检查器对新手更友好;在Nightly上遇到ICE(编译器内部错误)的频率,也从每周一次降到了每季度一次。
crates生态也更加可靠了:像jiff、polars、tauri等新一代项目建立在过去踩坑的教训之上,而老牌库如tokio、hyper、regex等,则在多年生产环境的锤炼下愈发稳定。
十年前,把Rust投入生产环境意味着你要不断造轮子、绕过种种已知和未知的坑;而现在,尽管在某些领域(比如我们团队在浏览器中用Rust)仍需小心,但对于大多数系统开发、后端工程来说,这些痛点已成为历史。
Rust让我们能专注于业务逻辑,同时构建出高性能、高可靠性的应用。
如今的Rust,已成为理想中的编程语言
当前,Rust不仅只是一个“安全的选择”,它更体现了一种前所未有的“开发者同理心”——在大型软件项目中非常罕见:构建系统简单而稳定,错误信息清晰到堪称模范,Lint工具智能友好,文档质量一流,IDE集成完善,还有强大的CI和回归测试体系……Rust给人的感觉,就像是一个程序员为程序员倾心打造的、充满同理心的项目。
十年前的我们能预见到今天的一切吗?也许,有些人确实预见到了。当时饱受现状困扰的一群人,看到了Rust的潜力——一门由他们这样的人设计的、从底层生态开始就考虑周全的语言。他们义务投身其中,把Rust一步步带到了今天。
正如Rust的原创作者之一GraydonHoare所说:
“如今的Rust语言,是那些具有前瞻性的机构大量投资、以及成千上万个坚信Rust未来能带来巨大价值的人共同努力的成果。”
十年前,我把时间和投资人注入的资金都押在了Rust上,因为我相信这种价值是值得追求的。当时大家的热情都非常有感染力,Rust的潜力显而易见,聪明的人迅速聚集。我很高兴这一切都有了长足的发展,也非常感谢每一位为此做出贡献的人。
我对接下来10年的期待
(1)构建更快、更简单
随着Rust社区工程能力和测试能力的增强,越来越多复杂或性能瓶颈明显的依赖库,正被更简洁高效的实现取代。我个人直接或间接受益的场景包括:链接优化、锁机制、回溯处理、平台优化代码、TLS、HTTP、Git、压缩算法、构建流程和工具链切换等
我特别期待Rust社区未来能重点关注以下方向:一个“纯Rust”实现且更少特殊化的标准库;减少对系统级链接器和原生库的依赖;完整的纯Rust加密库;更可靠的BTreeMap实现;Rust原生的游戏引擎(不是因为我做游戏,而是因为游戏开发者往往能带来最激进的性能优化,我很乐意从中受益)。
在性能层面,业界已经投入了大量专业资源。以我们团队最近的成果为例,Tably的编译时间已经整体下降了60%,涵盖前后端。其中大部分改进来自图表上未显示的元级别更改,如ThinLTO、前后端并行、增量编译、元数据流水线等。至于未来,我认为可能进一步带来优化的元级别更改包括:面向Rust的代码生成器、增量链接器、死代码清除、新一代trait求解器和cargo测试结果缓存。
(2)更好的可移植性,更少的#[cfg()]
目前,由于#[cfg()]的组合空间太大,CI中几乎无法覆盖所有合法选项、目标和特性。这导致许多代码路径未测试、不完整的文档、IDE功能缺失、以及大量unused_imports警告。
为了解决这个问题,Rust社区曾提议引入一种新的Lint机制,有种激进的做法是将#[cfg()]移入trait系统,通过wherePlatform:Unix或Platform:Avx2等条件来描述编译环境。这不仅能让编译器保证多平台编译,还能借助specialization实现平台/架构专用实现。
如果能做到这一点,不同构建模式之间的元数据就可以复用(如dev/test/release、多特性组合、多平台构建等),从而带来更少的重新编译、更快的CI,甚至让crates. io上基于MIR的缓存系统成为现实。
(3)万物皆可const
让一切代码都支持const计算,会减少对宏和构建脚本的依赖,把一部分运行时计算和panic提前移至编译时。目前Rust对const的支持还非常有限(比如不能有trait、不能申请堆内存),而且执行效率偏低,尚不适用于复杂场景。
假设所有代码都能在编译期运行,这种“全const”思路将极大简化语言本身。尽管有些代码如FFI、汇编还不具备移植性,但它们已变得越来越边缘。虽然社区曾尝试引入“effects”机制来支持这种能力,但我更希望我们能避开这些复杂的语法扩展,坚定走“const为先”的道路。虽然这条路困难重重,但从语言设计角度看,我认为非常值得。
(4)更简单的并发模型
目前async在某些情况下依然代价高昂,比如:’static生命周期约束导致代码复杂、无法原生处理取消操作(cancellationsafety)、很多trait和dyn使用受限。此外,异步和同步API的割裂、生态中不同框架的差异,也让“异步开发成本”居高不下。虽然曾有人尝试基于effects的方法,但目前看来并不理想。
值得一提的是,在Rust1. 0之前,Rust曾拥有一个用户态线程模型libgreen,它实现了无需割裂的并发模型,代价是性能差、维护成本高、不可移植,因此最终被移除。而随着工程能力提升,如今我们或许可以重新考虑这种设计。为此,我甚至打算尝试写个PoC:将std::{fs,net}包装为零成本异步接口,搭配fiber::{spawn,select},配合Rust的generator特性实现。
(5)开拓更多应用领域
举个例子,目前Rust在浏览器端的使用场景还没被充分挖掘。我们在实际开发中经常碰到一些棘手问题,比如:如何避免未定义行为(UB)、如何跨浏览器获取堆栈信息——这说明目前真正用Rust做浏览器端开发的人还不多。
我们目前使用的Web框架Leptos已经进化了很多,但还有不少打磨空间。而有些场景如快速原型开发、简单业务逻辑,可能永远不会成为Rust的强项,毕竟Rust在设计之初就有意选择了牺牲迭代速度来换取性能和安全。
当然,在大多数领域,Rust的渗透只是时间问题。GUI、机器学习、游戏开发等方向虽然仍受限于成熟生态的壁垒、高切换成本、团队文化惯性和工具链不兼容,但我认为这些障碍终将被Rust社区逐步攻克。Rust的发展从未停止,社区正以惊人的节奏推进着每一项突破。
结语
展望未来,Rust的发展路径令人兴奋。语言采用度越高,社区就拥有越多的工程和测试资源,进而推动更多的用户采用——这种“正向循环”正在加速。
未来十年,我们有理由期待Rust拥有:更快的编译速度、更高的语言可移植性、更广泛的应用场景以及更流畅的开发者体验。而我们也会继续致力于推动Rust的边界,探索它的更多可能性。
让我们举杯,再为Rust押注十年!
好啦,今天的内容分享就到这,感觉不错的同学记得分享点赞哦!
PS:程序员好物馆持续分享程序员学习、面试相关干货,不见不散!
点分享
点收藏
点点赞
点在看