Rust,zig和carbon:炒作,希望或地狱

https://www.bilibili.com/video/BV1Ju4m1w7DE

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

当然,我会帮您整理原文内容,并将其翻译成中文。以下是整理后的内容,我会尽量保留所有细节,不做省略或总结:

今天我们要讨论编程语言,特别是Rust、Zig和Carbon。我们将探讨它们是否是炒作、希望还是地狱。这个问题我们今天可能会回答,也可能不会。

我是一名开发人员,在Thoughtworks工作了一段时间。我的背景主要是VAP和云领域,但在过去五年里我一直在汽车行业工作,那里C和C++非常主导。我们不得不寻找替代方案,让我们这么说吧。

让我们直接谈谈这次演讲的动机。特别是在嵌入式开发和高性能应用程序方面,C和C++今天仍然是最大的玩家。然而,它们都有各自的缺点,大多数人都在寻找其他选择。所以今天的目标是讨论Rust、Zig和Carbon作为替代C和C++的候选者。

我们的目标不是给这三种语言排名,而是获得更多关于它们优缺点的见解,并更好地理解在什么情况下可能值得更深入地了解它们。我们不会深入研究每种编程语言的接口或语法,然后进行逐一比较。相反,我们想要理解每种语言的承诺和主张,看看它们各自试图实现什么。

我们希望在这次演讲结束时,你们都能对这些语言有所了解,并对它们产生好奇心,愿意尝试更多。我们也希望你们能更好地理解在什么情况下可能值得更多地参与和使用它们。虽然你们肯定会有自己的看法,但我们相信在这次演讲结束时,你们可以理解并尝试自己决定Rust、Zig和Carbon是炒作、希望还是地狱。

让我们先从Rust开始讨论,好吗?

谁以前写过Rust?请举手。大约一半的人。所以你们中的一些人可能比我更了解Rust。我先声明一下,我是Rust的粉丝,但我会尽量保持客观。

简单概述一下,Rust始于2006年,由Mozilla发起。背景是要编写一个新的或实验性的浏览器引擎,所以我们这里更多地谈论系统级编程。Rust的第一个版本发布于2015年,所以我们现在已经有8年的历史了。当前版本是1.7左右。

2019年,Mozilla裁员时Rust核心团队受到影响,Rust的未来在几个月内变得不确定。然而,在2020年,Mozilla和其他一些大公司成立了Rust基金会,这是一个非营利组织。所以现在看来Rust的进一步发展是稳定的。

正如Di指出的,我们想看看编程语言的主张是什么,看看它们是如何实现这些主张的。如果我现在去Rust网站,它直接就说了这三点:我们要确保你写的软件是高性能的、可靠的,我们还要确保开发的生产力。让我们看看他们是如何做到这一点的。

但在我们深入之前,我想强调一些其他有趣的事情。Stack Overflow有一份关于编程语言、工具和框架的调查或报告。多年来,Rust一直是最受喜爱的编程语言,使用它的人真的非常喜欢它。但同时,如果你看采用率,它一直很低,而且增长很慢。这很有趣 - 使用它的人喜欢它,但没有多少人使用它。

这种情况显然已经改变了,我认为这值得一提。因为我觉得在2020年或2021年左右,很多大公司说我们要押注Rust,我们要把它包括进来。现在,在Android 13中,21%的代码是用Rust写的。Rust是Linux内核中唯一的第二种语言。微软也在采用Rust来开发Windows的一些核心组件,虽然我找不到具体细节。但他们对此是认真的。

让我们来看看性能。在性能方面,我认为有不同的类别。我会说有一些事实更多地与语言设计有关。Rust没有运行时,没有垃圾收集,目标是让所有抽象都是零成本的。所以从设计上讲,与解释型语言或类似的东西相比,这种语言的性能相当高。

然后还有一层是在编译和优化级别上的。因为有时(不是总是)你可以做静态调度、零复制或函数的内联展开。这使它更进一步。另外有趣的是,编译器使用LLVM作为后端,所以在LLVM和后端的任何改进都会对Rust有利。

还有一些更模糊的东西,比如Rust有一个非常广泛的宏系统,所以你可以在编译时做很多事情,将高级代码展开成更低级的东西。这也确保了性能。

人们总是忘记,虽然你不能用并发解决所有的性能问题,但如果可以的话,在Rust中编写并发程序真的很容易。所以如果这是你提高性能的一个杠杆,那可能很有趣。

撇开所有技术细节不谈,比较语言的性能是相当困难的。很多人在这上面花了大量时间和乐趣。我只是看了一些结果。这里我们有用Rust和C++实现的不同算法,他们还做了不同版本的实现。我想可以说它与C++不相上下。有些地方C++更快,有些地方Rust更快,但我想它们处于非常可比的水平。如果你把Java或Python放在旁边,在性能上会有不同数量级的差异。

另外,性能可以是两种不同的东西。有时我只是想写我的程序,希望有一个好的性能。在Rust中,对于大多数情况,只需在构建时使用–release选项就能做很多事情,你很可能会从代码中获得良好的性能。

然而,有时你会遇到这种情况:我需要这个函数尽可能快。你真的要为此优化。有一本书专门讲这个,叫《Rust性能书》。我不会详细讲,但有很多内容。我想说,也许其他语言可以给你更多自由来做一些恶心的事情来提高性能。

这就把我们带到了下一个话题:可靠性。在可靠性方面,有不同的概念来确保你的软件是可靠的。其中一些真的是在语言层面上的。它有所有权和借用的概念,你不能有悬空指针,这根本行不通,编译器会打击你,而且比你想象的要频繁。

不幸的是,还有生命周期的概念,所以有时你必须说一个变量应该在作用域内多长时间或者在作用域内。生命周期很难,我经常为此挣扎。

然后你还有一些在其他语言中也能找到的非常现代的概念。你有Option和Result,这意味着你不能有null。你有很好的模式匹配,如果你对一个枚举进行匹配,它会告诉你:”哦,你忘了这种情况,也许你应该知道”。还有强大的类型系统。

所以语言中有很多不同的概念来确保可靠性。结果是,首先,有一类错误根本就不会发生了。所以你有静态内存安全性,这是有保证的,很多事情就是不会发生。但对我来说,当我真的在Rust中使用强类型系统,它编译通过时,就像”啊,它编译了,可能是对的”。没人能证明这一点,但你对代码就是有一种很好的信心。

我答应过不多谈汽车行业,但就在这里,在汽车行业有这个标准,MISRA规则。基本上它是一套规则,说你应该在C++中做这些事情,然后你的代码可能是安全的。它的工作方式是,你有一个文本文档,里面有所有的规则,然后你有开发人员一个一个地检查这些规则,修复代码。我发现有趣的是,如果你使用Rust,70%的规则就不适用了,因为你的代码根本不会编译。我想这是一个很好的比较,如果你考虑语言的可靠性。

关于生产力,有几点。Rust有一套很好的工具,要么随之而来,要么在生态系统中开发出来,比如构建工具、如何安装它、编辑器支持等。这些都很无聊,就是能工作。我想为不同的目标交叉编译,我只需安装它,就一个命令行,它就能工作了。不像其他经历…

我认为对于愿意花时间学习的有经验的开发人员来说,这很好。有时学习可能很困难,因为这门语言非常简约。它使用非常短的关键字,有很多语法糖,所以你必须学习惯用法,学习”Rust式”的写法。但我想如果你克服了这一点,那就真的很好。

正如我之前指出的,有时取悦编译器可能很难。我甚至会卡住,编译器说”不,你不能这么做”,然后你就像”是啊,好吧”。你真的必须退一步,用不同的方式写,因为你不能以那种方式确保它是安全的。

Rust社区活跃且不断增长。我特别想指出免费书籍的数量。《通过例子学Rust》、《Rust程序设计语言》、性能书,还有嵌入式的书,这些都是免费的,而且我认为它们都相当不错。

我指出编译可能会很痛苦,不仅是为了取悦编译器,有时也会很慢。因为这门语言非常简约,你必须使用很多宏。它甚至没有日期数据类型,没有序列化,所以你必须引入一个模块来做这些事情。这可能会使编译时间变得非常慢。但你总是可以达到可以进行TDD的程度,我想这是主要的。

它与C++配合得很好,因为你必须创建绑定才能使用C++函数调用。我想这是可行的,但由于你必须创建这些绑定,如果你有这样一种情况:你开发系统的C++部分,而你的R系统,我想那可能会很痛苦。我认为我们稍后会听到其他概念,在这方面会更有益。

总结一下,我认为Rust成功地做到了它声称要做的事情。某些好处显然是有代价的,有时可能是编译时间,有时可能是当你试图取悦编译器时会有一些紧张。但它显然也找到了自己的位置,不仅在嵌入式系统编程中,我认为很多人用Rust编写命令行工具。Web Assembly也支持Rust,出于某种原因,在区块链和加密世界中也很流行。我的意思是,如果你在网上搜索Rust远程开发工作,那肯定是加密相关的。这不是我的菜,但它在那里非常普及。

我找到这句话,我不记得是从哪里来的,所以我不能引用出处,但Rust”是那些打算长期存在的代码的好选择”。我想这很好地总结了它。

让我们来谈谈Zig。

好的,让我们来谈谈Zig,先了解一下情况。请举手示意谁已经实现或了解Zig语言?没有人?很好,那让我们来多谈谈,了解更多关于Zig的信息。

Zig语言很好,因为Zig有两种不同的风格。大多数语言更纯粹是语言,但Zig提供了可以用作编程语言,也可以用作工具链的功能。这是第一个重要点,很有趣,因为当你有这两种风格时,它支持你做更多的事情,或者使用其中之一。它是一种通用的编程语言和工具链,支持你构建更强大、更优化和可重用的软件。

我想强调的一点是,当你提到强大时,我们可以将其与弹性联系起来。但这里因为它更专注于高性能应用程序,所以强大的想法是覆盖处理内存分配或更接近硬件的关键区域时的边缘情况。所以Zig的强大正是触及这些边缘情况。

优化是因为Zig针对性能和高质量软件。这在嵌入式生态系统或接近操作系统的关键空间中是至关重要的。这意味着性能和高质量很重要。可重用是因为你可以在许多领域使用它,不仅在低级别,而且还支持高级别。所以它增加了你可以使用这种编程语言的领域。

有趣的是,这种语言相当新,不到十年。2015年,Andrew Kelley创建了第一个git init,现在我们仍然没有1.0版本。如果你想要Zig的稳定版本,我们还

好的,我继续为您翻译整理剩余的内容:

需要等待一段时间,但它仍然很有前景。同时,尽管这种语言非常年轻,在今年的Stack Overflow调查中,它被列为第三受欢迎的语言,仅次于Rust和Elixir。它引起了人们的注意,也是薪酬最高的语言。我认为它是薪酬最高的语言可能是因为我们拥有这种技能的开发人员很少。但从另一个角度来看,它并不是那么受欢迎。我相信当我问你们是否了解或使用它时,得到的结果与这些调查结果完全一致。在受欢迎程度方面,Zig非常接近Prolog和Forth,所以你可以衡量它的受欢迎程度。

现在我们更多地了解了这种语言,可以理解它的目的,我们很有兴趣弄清楚在哪些真实场景中我可以使用Zig,甚至在实际工作中使用它。我们也有一些公开的案例,开始使用Zig作为语言或工具链。

第一个是Bun,它是一个JavaScript运行时环境,建立在Zig之上。我可以说它是Node.js的替代品,因为Node.js是用C++编写的V8引擎。而Bun正是为了代替使用WebKit JavaScript引擎而使用Zig来提高性能。根据目前的结果,与Node.js和Deno相比,Bun似乎更具性能。这是我们可以看到Zig在行动中的一个教育案例。

第二个是TigerBeetle,这是一个数据库。再次强调,数据库涉及性能,以及数据库应该有多安全和弹性。Zig也支持这一点,它是TigerBeetle核心的一部分。TigerBeetle是一个针对金融领域的数据库。

这两个用例更多地关注于将Zig作为编程语言使用。但对于Uber来说,他们更多地将Zig用作工具链,用于构建系统和交叉编译。稍后我们会更深入地讨论这一点。但你可以很容易地看到这三个大型且公开的案例在现实生活中使用Zig。Zig是一种非常新的语言,所以它引起了我们更多的注意。

但为什么是Zig呢?我们有这么多语言 - Go、Rust、Carbon,我们有这么多语言,为什么还要再添加一个?这就是Andrew Kelley提到的原因,Zig有它的存在空间。为了回答这个问题,他提到了四个步骤,我们会快速讨论这四个步骤。

第一步,正如我提到的,是高质量性能。当你谈到为这个领域构建应用程序时,我们真的需要有更多的控制权。关于内存,你如何分配,你可能不能使用垃圾收集器,你需要更多地了解内存分配。使用或选择能给你更多性能的技术。同时,可能还需要触及C ABI以获得更好的兼容性,因为你可能需要在一个主机上构建你的应用程序,然后在不同的主机上运行这个应用程序。我们需要考虑所有这些点,这是当你考虑高性能软件时的第一个非常强大的点。

第二点是,大多数语言不能满足这些需求。例如,我们有Java或Python或其他语言,有时不支持这些原则或设计标准。这就是为什么我们有大多数主流语言,我们可以使用它们。如果你想使用,你可能会遇到问题,因为如果你选择了错误的技术,你真的无法支持这些用途或产品。

第三步是,好吧,既然大多数语言不支持我构建,为什么不用C++呢?然后Andrew Kelley说,C++太多了。也许有很多有趣的东西引起了我的注意,但有时它违反了一些原则,所以不是那么清晰。但它太多了。Zig并不走C++的老路。所以不用C++。

然后我们有C,为什么不用C呢?但问题是C很好,但C已经有一些预处理器宏,我们如果不小心使用这些特性,就会遇到一些问题。因为有时你可以在使用它时犯错误,然后你可能会遇到问题。我们有统计数据证明我们有漏洞,也有很多缓冲区溢出的问题。也许C和C++无处不在,bug也无处不在。所以一件事与另一件事有关,但很容易犯错误。

例如,这里有一个简单代码的例子。当我提到容易犯错误时,我们这里有一个简单的if语句。如果是true,让我们打印”hello”,如果是false,想法是另一个流程。问题是,当你使用宏时,在第2行到第6行,你可以取消定义true和false。这意味着我们使用布尔值的方式,你可以调整和改变true,比如说把true链接到零,我的意思是相反。你可以这样做,这是可能的,这就是为什么我提到很容易犯错误。

当然,这里很清楚,我相信我们不会完全按这种方式实现。很明显这是错的,但当我们遇到业务逻辑、业务实现时,很容易引导你犯错误并遇到这种错误。这就是我提到的错误,你可以很容易地犯错误。所以最后,当你把true关联到零时,当我们执行这段代码时,结果是”oh no”,因为它是按我们实现的方式,但这不是我们期望的。这就是为什么我们有Zig。

Zig在这里更多的是为了在三个不同的角度满足需求:作为一种简单的语言,在编译时,以及作为工具链的构建系统。这三个主流领域是Zig的强项和区别所在。

让我们快速谈谈这一点。简单的想法是成为一种简单的语言,对Zig来说,简单的语言不仅仅是易于使用或语法简单,而是更多地满足整个开发者体验,远不止语法。

这里我们有一个简单的”Hello, World”示例,因为每次我们开始学习一种语言时,当然第一次接触语言就是”Hello, World”。这里Zig的想法再次是要成为C的替代品,因为Rust更多地与C++有直接联系,但这里的想法应该是没有问题的C。

在这里,我们有一个简单的真正的”Hello, World”。在第一行,你可以看到一些我们称之为内置的东西。你可以看到@import是你可以访问标准库的方式。从标准库中,你可以访问许多接口。例如,你可以访问或拥有你的测试框架,或调试应用程序,或日志,或甚至是解析器。我们有很多包,很多功能,你可以使用,Zig为你提供了一切。

然后你有main,就像入口函数一样,没有太大区别。然后你有try,然后你可以打印。没有太大区别,但我想强调的一点是,如果你只下载访问ziglang.org下载,你可以下载非常简约的tball,然后你就有了Zig。你不需要花太多时间去配置或处理CMake或C或ninja或所有这些你可能在开始使用C时遇到的东西。因为C不仅仅是C,还有整个C的基础设施。然后我们就有了问题。对于Zig来说完全不同,它非常流畅。下载,然后你就有了CLI,然后你可以构建、编译、交叉编译,一切都很容易。

我们这里还有一个简单的方法来控制内存,在第4行,它让你访问和理解接口,以不同的级别或不同的方式控制内存。然后你defer,然后你做你想做的任何事情。你不需要改变任何东西来控制内存。当然,这是一种不同的方式,因为对于C,我们有malloc,所有这些方式。但对于Zig来说,这是一种不同的方式。但你需要控制内存,它给你更多的方式来做你想做的事,而不是使用一个你不知道背后发生什么的客户端库,你不知道控制内存的更好方式是什么技术。

Zig的第二点是编译时。编译时,因为Zig的操作方式给你更多的控制权,让你在编译时实现。Zig是一个以编译为中心的特性,这意味着它在编译时预先进行了很多检查和验证。这是Zig提到的一点,Zig让你看到你有的错误。它也加速了性能,更具性能,因为它不允许你以错误的方式做事,一切都完全在编译时进行,而不是在运行时。所以它们是预先进行的。

例如,在编译时,我们有泛型。这里我们有一个测试,你在验证范围并传递一个类型。在编译时,你使用comptime关键字的函数实现。这是编译器知道它需要在编译时验证一切的方式。在这里,它们正在验证获取这个类型,这个我正在传递的类型。在这个编译过程中,我也可以检查、验证我是如何为这个泛型实现逻辑的。这很简单,但Zig的强大特性是在编译时你可以做很多事情。

最后一点是交叉编译。使用Zig进行交叉编译,你只能使用Zig CLI,然后你可以编译你的Zig代码,或者你可以使用Zig作为编译器对C++或C代码做同样的事情。所以使用Zig来编译非常好。所以你可以用Zig来编译Zig、C和C++,甚至可能是CoZy。也许你可以有一个项目,你可以使用Zig和C++共存。你可以这样做,而且很容易。在一个简单的命令行中,你可以做很多事情。

这里有一个例子,就是我之前提到的Uber的案例。Uber有一个复杂的环境,他们有很多不同的主机,比如Linux或macOS。然后你有不同的目标。这意味着你在你的目标主机上构建和编译你的应用程序,然后在不同的主机上执行。使用Zig,他们能够从庞大的基础设施转移到一个单一的归档文件,然后更好地管理。

总结一下,对于Zig来说,现在说它成功替代C还为时尚早。我们需要等待更多,等待稳定版本,看看事情真正如何运作。但现在真正有前景的是,你可以使用Zig作为交叉编译和构建系统的工具。这里有三点:Zig在与C和C++的互操作性、交叉编译和构建系统方面非常强大,这很有趣,很有前景。在编译时你也可以做很多事情。

让我们来谈谈Carbon。

这会很快,别担心,因为关于Carbon最有趣的是…嗯,它是去年由Chandler Carruth在C++ North会议上首次向更广泛的观众介绍的。它得到了Google的支持,所以Google付钱给一些开发者来推动这个项目。

让我直接说明一下预期:它是实验性的。没有编译器,没有工具链,甚至对于语言规范,他们说可能是2024年,也可能是2025年,我们不知道。所以我们还需要几年才能在生产中使用Carbon。然而,我放了这个GitHub的提交图表。整个语言在GitHub上演变,你可以在那里关注它。有事情在发生,人们正在投入资金。

当我们把Carbon放进来时,我发现它应该是C++的真正继承者,而不是像我们看到的Zig和Rust那样的替代品。但类似于我们从JavaScript到TypeScript,从Java到Kotlin的过渡,Carbon应该是C++的继承者。

由于没有太多可以测试的东西,我们可以假设Carbon的性能如何…但我们可以非常简要地看一下概念。因为如果你想成为C++的继承者,你需要有无缝的双向操作性。你应该支持C++开发者,应该有良好的学习曲线。C++的某些概念和习惯应该适用,你希望有一个好的迁移。

如果我想要这种操作性,我可以做两件事。我可以制作C++的子集,比如现代C++,或者我可以有一个超集,你知道,C++有的一切我都可以用Carbon做。他们走的是不同的路,因为他们说,哦,我们要在旁边建立一些东西,只需绑定C++有的每个数据类型,每个概念。这意味着它有点要么成功,要么失败。它要么有效,要么无效。

但有趣的是,为了能够从C++调用Carbon,反之亦然,需要在幕后进行大量工作。你需要生成Carbon代码,你需要生成C++代码,可能你需要C++20标准来做这个。

文章目录