撰稿 | 云昭
出品 | 51CTO技术栈(微信号:blog51cto)
众所周知,由于其根源于 Mozilla,Rust 在历史上与系统编程联系在一起,它对安全性、速度和并发性的承诺,使其在基础设施层面得到了广泛采用。这种地位的上升引发了一个有趣的问题:Rust 在传统上由动态语言主导的领域是否拥有更高的地位?
近日,一场汇聚了新兴语言的主要开发者的会议P99 CONF ,为我们带来了Rust与Zig如何相互借鉴,并让与会者们参与了挑战C++、Go甚至Java等主流语言的探讨。且让我们一探Rust与Zig的未来。
一、Zig可以借鉴Rust,反之亦然
世界上伟大的事物往往是完全开放,既可以和而不同,又可以相互借鉴。Zig与Rust之所以快速成为全球编程社区的“宠儿”,也是做到了开放与借鉴。
1.Zig学习Rust哪些?
Bun的创建者Jarred认为,Zig可以Rust那里引进“有限的编译时概念”,比如在各种类似作用域的情况下的一些借用检查器。此外,Zig安全方面还比较欠缺,两个明显的例子就是,还可以返回指向堆栈内存的指针,例如堆栈分配的缓存区,这都是不应该做的。
Zig语言还非常新,但诞生之初就懂得借鉴。比如向Go借鉴了延迟(defer),即延迟键盘和语言。与Go实现的区别在于,它是针对每个作用域的,而不是针对每个函数的。在 Go 中,defer 会将其附加到函数的末尾,而对于 Zig 来说,它位于作用域的末尾。这通常就是开发者进行资源清理的方式。
但Zig的延迟做的还不够好, 至少有某种形式的析构函数,因为它很容易被忘记。“有时我确实希望有构造函数和析构函数……但我的心情很复杂。”
2.Rust羡慕Zig什么?
Rust主要开发者Carl,则表示了Rust对于Zig编译速度的羡慕。“Zig 的编译速度肯定要快得多。Rust 肯定会从中受益。”
Rust目前的一个痛点就是:一旦你摆脱借用检查器而使用 Rust 进入不安全代码,它就很不符合人体工程学,而事实上,在编写nice的不安全代码方面,Rust其实有许多地方可以改进。Carl表示:我们编写的不安全代码比典型的应用程序开发人员多得多,因为我们正在构建这些类型的原语。Zig在这方面可以给Rust以灵感。
P99 CONF 的长期支持者Glauber,认为 Zig 有两件事可以让 Rust 受益匪浅。第一个是comptime。comptime 是Zig一个非常好的特性,即在编译期引入自身作为胶水语言来生成代码的能力,甚至被Glauber称为天才之举,“我希望每种语言都有这样的功能。
C++中的模板系统与 comptime 相比……根本不在同一个级别。”
可能很多人不太熟悉comptime, 简单来说,它允许开发者在编译时评估任意代码。许多语言都有类似模板的语法,然后还有一些其他变体,一些其他方式来具有编译时标志、功能和参数。这也是类型系统的工作原理。例如,标准库中的 ArrayList 类型接收 comptime 类型参数,然后就有一个该类型的切片。这有点像编译时的duck-typing类型。
举例来说,Zig用它来生成用于源映射解析的查找表。sourcemaps 使用这种编码 VLQ。“如果我们生成此查找表,则源映射编码速度将比以前快 18%。最初,我们是在运行时执行的。”Zig 使其变得非常简单,因为只需传递关键字即可。顶级作用域中的任何内容都是 comptime,否则,就可以将其传递到作用域中的关键字 comptime 中。
第二个,是 Rust交叉编译到不同的平台,是一个非常痛苦的事情。这方面Go 做得非常好, Zig 也比 Rust 做得更好。
交叉编译方面,Carl还透露了Zig的情况。“现在在 Bun CI 中,我们在 Linux 机器上为所有不同的平台、每个 Zig 部分构建每个目标文件。因为每台机器都有大量内存以使其编译速度更快。因此,我们在 Linux 上构建所有 Zig 代码,即使它是针对 Mac OS 的。”
二、用C的人为什么讨厌Rust,喜欢Zig
Rust 一直是注重性能的 P99 CONF 社区的宠儿。即使我们以 C++、Go 甚至 Java 的令人印象深刻的性能成就案例研究为特色,讨论也不可避免地转向“但为什么不是 Rust?”
很多人习惯于C,将C用于高效工作,因为C语言确实让你的移动速度快得令人难以置信(直到出现错误)。他们选择Rust,尝试像C一样编写Rust,最终都会遇到Rc<RefCell<...>>,unsafe{...}等。
这种大量的错误报告和“调试地狱”会带来非常强烈的负面反应。
但这并不意味着Rust太难了,其实有能力用C编写生产软件,就绝对有能力使用Rust。更多地在于,“当C方式对我很有帮助时,我不愿意学习Rust方式。”
这反而是Zig的利基市场。
如果您已经了解 C,您可以在几天内学习 Zig,并且比 C 更有效率。在我看来,这就是 Zig 的价值主张。它与 C 非常相似,您的大多数模式和根深蒂固的经验都可以利用。你学习了 Zig 的 comptime,然后,你就掌握了带泛型的 C 语言。您可以毫无障碍地依赖现有的 C 项目和库。Zig 是“我在 C 语言中很有生产力,但想要更好的功能”语言。
三、Java开发者不妨考虑学Rust
“Rust并不是太困难。我是一个巨菜的菜鸟,连我都可以在大约一个月内写出一些不错的Rust。”
虽然旧版 Java 很简单,但大部分时间都花在学习库、构建系统或非常复杂的应用程序服务器上。这3个部分非常复杂。编写 Spring MVC Web 应用程序非常复杂。
“我们公司迁移到 Rust,花了大约 1 个月的时间才适应 Rust,无需处理 C 指针、内存映射等低级内容。”
部署 Rust Web 应用程序比处理 Java 应用程序服务器和 WAR 容易得多。为什么Java应用服务器有这么多bug?
20 多年过去,它们仍然无法获得诸如重新加载而不泄漏或数据库连接池可靠而不挂起连接之类的东西。
“JDBC 的编写方式使得池无法强制关闭卡住的连接;卡住的连接会随着时间的推移而累积,直到服务器挂起。”
这表明Java J2EE应用服务器的整个概念是错误的。每个曾经使用过websphere的人,web logic都会把他们折磨到“地狱”。即使是最小化的 Tomcat 也远未消除错误。JVM 本身正在崩溃。“我还没有看到任何 Java 应用程序后端或 GUI 不会因为内部 JVM 错误而崩溃。”
Rust 需要的内存比 Java 少 10 倍,速度比 Java 快 4 到 10 倍,编译失败很快就会得到修复。不需要应用程序服务器和巴洛克式构建工具(变形的工具)。Rust 就可以,无需开始用 Java 编写新的应用程序。
Rust 有相当高级的库,如 Rocket.rs (rust) 和微型 Web 框架,如 scalatra.org (scala),这两种类型都非常容易上手。而且使用起来也要容易得多:所有内容均已键入,并且类型信息也可用作文档。
四、Rust在后端项目的软肋
也有一种观点认为,Rust不适合大型项目。因为Rust 项目是 AOT 编译的二进制文件,需要不断维护才能使其不断变化的包保持最新。此外,项目越大,linting 越慢,分析器越慢,构建时间也越慢。
也就是说,Rust 的借用检查器并不是大型项目中真正令人头疼的问题。然而,你需要学习如何移动、复制或借用内存的各种方法以及不自然的生命周期语法需要很长时间才能深入理解这些背后的真相。