在锈迹中编程是否更节能?

2022-02-20 21:14:57

Rust是一种编程语言,作为一组开源项目实现。它将C等系统编程语言的性能和资源效率与Java等语言的内存安全结合起来。Rust于2010年作为Mozilla的一个研究项目启动,2015年推出Rust 1.0。在2020,支持锈从Mozilla转移到锈基金会,一个非盈利组织,作为亚马逊网络服务公司(AWS)、谷歌、华为、微软和Mozilla之间的伙伴关系而创建。该基金会的使命是支持锈菌的生长和创新,会员公司在第一年从5家公司发展到27家公司。

在AWS,锈蚀很快成为大规模建设基础设施的关键。鞭炮是一种开源虚拟化技术,为AWS Lambda和其他无服务器产品提供了支持。2018年,它作为我们在Rust实施的第一款著名产品公开发布。我们使用Rust来提供服务,比如亚马逊简单存储服务(Amazon S3)、亚马逊弹性计算云(Amazon EC2)、亚马逊CloudFront等等。2020年,我们推出了基于Linux的容器操作系统Bottlerocket,它是用Rust编写的,我们的亚马逊EC2团队使用Rust作为新的AWS Nitro系统组件的首选语言,包括敏感应用程序,如Nitro Enclaves。

在AWS,我们相信领导者创造的比他们消费的更多,并且总是比他们发现的更好。2019年,AWS自豪地成为Rust项目的赞助商。在2020,我们开始雇用锈病维护者和贡献者,我们与谷歌、华为、微软和Mozilla合作创建锈菌基金会,以支持锈病。AWS正在投资锈菌的可持续性,我们认为应该使用这种语言来构建可持续和安全的解决方案。

资料来源:IEA(2021年),按数据中心类型划分的全球数据中心能源需求,2010-2022年,https://www.iea.org/data-and-statistics/charts/global-data-centre-energy-demand-by-data-centre-type-2010-2022.版权所有。

在全球范围内,数据中心每年消耗约200太瓦时。这大约是我们星球上所有能源消耗的1%。关于能源使用的细节,有几个非常有趣的事情。如果你看一看能源消耗的图表,可以追溯到2010年,顶线基本上是平的。这与我们的行业在同一时期经历的大数据、机器学习和边缘设备的巨大增长极为违背直觉。

第二个有趣的细节是,虽然图的顶线是平的,但在图中,传统、云和超规模数据中心的分布在同一时期发生了巨大变化。这些云计算和超规模数据中心一直在实施巨大的能效改进,而向云计算基础设施的迁移一直在保持数据中心的总能源使用平衡,尽管存储和计算在十多年来出现了巨大增长。

有太多的数据中心效率改进需要列出,但这里有几个例子。在计算方面,我们在硬件方面进行了效率改进,并实现了更智能的资源利用,以减少空闲时间。通过支持多实例和多租户,我们减缓了服务器的增长,提高了存储的驱动器密度和效率。我们还采用了更节能的建筑材料和冷却系统。

尽管这个成功故事令人难以置信,但它提出了两个问题。首先,现状够好吗?将数据中心能耗保持在全球能耗的1%是否足够?第二个问题是,未来能源效率的创新是否会继续跟上存储和计算的增长?考虑到我们所知道的无人驾驶飞机、运载机器人和车辆的爆炸性增长,以及支持这些技术所需的难以置信的数据消耗、处理和机器学习培训和推理,能效创新似乎不太可能跟上需求。

到目前为止,我们讨论的能效改进是AWS的责任,但就像安全一样,可持续性也是一项共同的责任。AWS客户负责在存储策略、软件设计和计算利用率方面进行节能选择,而AWS在硬件、利用率功能和冷却系统方面拥有效率。我们还在可再生能源方面进行巨额投资。

AWS有望在2025年前让我们的数据中心100%使用可再生能源,但即使是可再生能源也会对环境造成影响。目前数据中心使用的200太瓦时的能源将需要大约50万英亩的太阳能电池板。许多太阳能电池板的开采、制造和管理都会对环境产生重大影响。因此,正如AWS高级副总裁彼得·德桑蒂斯(Peter DeSantis)在re:Invent2020上所说,虽然我们对可再生能源的成功感到非常自豪,“最绿色的能源是我们不使用的能源。”

可再生能源不应取代能源效率作为设计原则。正如卓越操作、安全性和可靠性一直是传统软件设计的原则一样,可持续性也必须是现代软件设计的原则。这就是为什么AWS宣布了AWS良好架构框架的第六个可持续性支柱。

在实践中,这看起来像是放松非关键功能的SLA,并优先考虑资源使用效率。我们可以利用虚拟化,并允许更长的设备升级周期。我们可以尽可能利用缓存和更长的TTL。我们可以对数据进行分类,并实施自动化的生命周期策略,以尽快删除数据。当我们选择加密和压缩算法时,我们可以将效率纳入决策标准。最后,但并非最不重要的是,我们可以选择用节能编程语言实现我们的软件。

几年前有一项非常有趣的研究,研究了能量消耗、性能和记忆使用之间的相关性。这是可持续发展领域的一个非常常见的话题。鉴于我们对服务业的能源或碳使用了解甚少,有没有一个指标可以作为替代指标?我是否可以查看现有的服务仪表盘,了解基础设施成本、性能、内存等,并使用我看到的趋势来推断服务能耗的趋势?

这项研究所做的是用27种不同的编程语言实现10个基准问题,并测量执行时间、能耗和峰值内存使用。C和Rust在能源效率方面明显优于其他语言。事实上,它们的效率大约比Java高50%,比Python高98%。

C和Rust比其他语言效率更高,这并不奇怪。令人震惊的是,差异之大。广泛采用C和Rust可以将compute的能耗降低50%——即使保守估计也是如此。

所以问题是为什么不使用更多的C?语言和开发工具非常成熟,开发人员社区的规模比Rust大得多。在2021的开源峰会上,Linux的创建者Linus Torvalds承认在C中实现代码可以像玩链锯一样。作为一名终身的C程序员,托瓦尔兹知道,“[C的微妙类型交互]并不总是合乎逻辑的,而且对几乎所有人来说都是陷阱。”

托瓦尔兹称生锈是他见过的第一种语言,实际上可能是一种解决方案。Rust提供了C的能量效率,而没有未定义行为的风险。我们可以在不失去记忆安全好处的情况下将能源消耗减半。

几项分析得出结论,在C/C++中发生的高严重性CVE中,70%以上可以通过在Rust中实施相同的解决方案来预防。事实上,支持Let’s Encrypt项目(2.6亿个网站的证书颁发机构)的非营利组织互联网安全研究小组(ISRG)的目标是让所有对互联网安全敏感的基础设施生锈。正在进行的项目包括在Linux内核中支持Rust,以及将curl迁移到TLS和HTTP的Rust实现。

再看看那项关于相关性的研究,我们得到的不仅仅是能源消耗的测量结果。中间一列显示了执行时间的结果,Rust和C的时间非常相似。这两种语言的执行速度都比其他语言快。这意味着,当您选择在Rust中实现软件以实现可持续性和安全性优势时,您还可以获得C的优化性能。

Tenable是一家专注于曝光可见性工具的网络安全解决方案提供商,他们有一个sidecar代理,可以过滤掉不必要的指标。它是用JavaScript编写的,已经在生产环境中工作了几个月,但由于扩展,性能开始下降。Tenable决定用更高效的语言重写过滤器,他们选择Rust是因为它的性能和安全性。结果是,中位数和P95的潜伏期都提高了约50%。

50%的性能改进是很好的,但下面是该迁移的一些其他图表。Tenable的CPU使用率和内存使用率分别降低了75%和95%。这是巨大的节约,这不仅仅是节约了美元,而是节约了能源。以下是节能、可持续实施的图表。

如今,Rust正被用于运送真实世界的生产软件,但开发者并不是为了减少碳排放而选择Rust。当我们问Rust开发人员为什么开始使用Rust时,到目前为止,最常见的答案是运行时性能的一些变化,无论是因为Rust更快,还是因为Rust具有更可靠的尾部延迟。它几乎总是关于性能。

Discord最初是一家以Python、Go和Elixir为主的商店,他们的一项关键Go服务出现了问题。这是一个非常简单的服务,但尾部延迟很慢。因为Go是一种垃圾收集(GC)语言,当对象被创建和释放时,垃圾收集器经常需要停止程序的执行并运行垃圾收集过程。当GC运行时,进程无法响应请求,并且在运行时可以看到CPU上的峰值和响应时间图。

为了解决这个问题,Discord决定尝试在Rust中重写服务,结果如下。Go实现在左边,Rust实现在右边。虽然GC尖峰模式在锈迹图上消失了,但真正惊人的区别是变化的幅度。Go和Rust图实际上使用了不同的单位。

生锈版本的速度是所有版本的10倍以上,最糟糕的尾部延迟减少了100倍。这些都是难以置信的改进,因为服务器能够更高效地响应请求,所以需要的服务器更少,这意味着使用的能源更少。虽然Discord没有决定开始使用生锈来减少能源消耗,但这就是影响。

再说一次,Rust并不是第一种高效的语言。C语言已经存在很长一段时间了,但Rust是第一种高效且不牺牲安全性的主流编程语言。在C和C++中写的所有严重的安全漏洞中,有70%是由于内存不安全,而生锈会给你带来效率,而不会感觉到你在玩火。

大多数语言通过在运行时使用垃圾收集器自动管理内存来实现内存安全。垃圾收集器跟踪对内存块的未完成引用,当所有引用都超出范围时,可以释放关联的内存。

Rust没有使用垃圾收集器来维护安全,而是使用所有权和借阅检查。所有权相当简单,但对Rust编程语言的其他部分有着深刻的影响。在Rust中,所有内存都属于一个变量。该变量称为其所有者。一次只能有一个所有者,但数据的所有权可以传递。

首先,这里是一个使用Go传递消息的示例。在左侧,我们创建一份礼物,然后通过通道发送。在右边的其他围棋程序中,礼物会被收到并打开。Go的垃圾收集器将为我们管理内存。然而,在左边的代码中,我们在将礼物发送到频道后意外打开了它。礼物将被打开两次,导致一个错误。

下面是与Rust相同的消息传递示例。礼物被创造和分配。我们说'gift'变量拥有数据。礼物的所有权被转移到渠道中。渠道消费者收到礼物,获得所有权,并能够打开礼物。如果我们在将礼物发送到频道后试图打开它,编译器会对我们大喊大叫,因为我们违反了所有权规则。我们已经看到锈菌如何帮助我们预防虫子。

因为Rust强制执行只有一个变量拥有数据的规则,所以当该变量超出范围而不冒充所有权时,就不可能访问数据。Rust利用了这一点,并将在该点自动释放内存。无需手动释放内存。

Rust的所有权模型是类型系统的一部分,基于一个称为仿射类型的概念。仿射类型规定每个变量最多使用一次。关键是定义“使用”的含义。在生锈的情况下,用户要么移动数据,要么丢弃数据。通过使用仿射类型,Rust编译器能够对程序进行推理并执行其所有权规则。

Rust使用的仿射类型系统基于上世纪90年代初的工作,当时一些人试图设计一个无垃圾收集器的lisp。虽然取得了成功,但他们发现,由于无法对同一数据段进行多个引用而引入的过度复制,他们失去了很多运行时性能。

这就让我们看到了第二个让锈迹得以存在的创新:借阅检查器。在编写大型程序时,我们倾向于使用抽象来帮助组织想法。你可能熟悉的一种抽象是函数。函数通常需要参数。如果只有所有权,要调用函数,我们需要将数据的所有权传递给函数,函数需要在返回时将数据的所有权传递回。这需要复制周围的内存,并且是无垃圾收集器lisp性能挑战的根源。

为了解决这个问题,Rust允许您借用数据。所以,如果我们有天赋,我们就拥有它。这是我们的。如果我们的朋友想欣赏它,她可以借一会儿,但她必须把它还给我们。此外,当我们的朋友借礼物时,我们不能将礼物的所有权移交给其他任何人,因为礼物目前正在被借。最关键的是,Rust编译器执行这些规则,所以我们的朋友不能带着礼物跑了。由于Rust编译器强制执行这一保证,因此在借用数据时,不必复制内存。内存保持在原来的位置,并传递指针。指针保证是有效的。当你把它们放在一起,你就有了一个高效的系统,可以防止错误,即使程序变得更大、更复杂。

防止内存不安全的系统也可以防止数据竞争,这是一种并发错误。当两个或多个线程同时访问同一数据,且其中至少一个访问是变异时,就会发生数据竞争。对所有权和借用进行建模的类型系统能够跨多个线程维护相同的保证,从而更积极地使用并发性。

下面是一个例子,说明了向Rust应用程序安全地添加并发性是多么容易。我们有一个函数,它遍历一个数字数组,并对所有偶数求和。这是一个高度可并行化的操作,对于非常大的阵列,我们可以看到通过添加并发性,函数的速度显著加快。

左侧显示单线程版本,右侧显示使用人造丝库的并行版本。看看这些功能有多相似。通过基本上编写相同的代码,您可以在没有危险的情况下获得并发的所有功能。唯一的区别是我们使用par_iter()方法而不是iter()。

并行版本将把计算扩展到多个线程,同时避免复制作为参数传递的数字数组。由于Rust的所有权和借阅检查系统,人造丝能够安全地提供这种API。所有保证安全的检查都发生在编译时。

希望到现在为止,我们已经让你们对锈迹感兴趣,并开始你们在云端的可持续发展之旅。那么从哪里开始呢?好消息是,你需要的所有内容都可以在网上获得,你可以去一些地方开始。

首先,您需要学习Rust编程语言。铁锈书是开始学习语言的绝佳资源。它将帮助你安装Rust工具链,并教你该语言。该网站还提供练习和大量代码示例供阅读。如果你在任何时候遇到困难、有问题或需要澄清,你可以在用户论坛上发帖或直接在社区Discord服务器上聊天。Discord服务器通常是获得帮助的最快方式。那里总是有活跃的人可以实时回答问题。

一旦你浏览了Rust网站,你应该会很舒服地开始建造东西,但我们还需要另一个资源来深入挖掘。《锈壳》是Jon Gjenset的youtube频道。他确实深入研究了各种与生锈有关的话题,揭开了引擎盖,解释了事情是如何运作的。他的视频长达数小时,但我们不断听到人们说这些视频对学习锈菌有多么重要。

铁锈很难学。在对2020年Rust用户调查做出回应的8000多名开发者中,只有大约100人被认定为“专家”,在表示不再使用Rust的受访者中,55%的人认为学习或生产力是他们放弃该语言的原因。

经验丰富的工程师需要3-6个月的研究,并获得主题专家的支持,才能在生锈问题上取得成效。一些工程师将学习锈病比作学习吃蔬菜,虽然他们中的许多人一旦有了生产力就喜欢锈病,但许多工程师决定不学习锈病,或者在他们变得有生产力之前放弃努力。锈病对可持续性和安全性的潜在影响只有在我们把西兰花变成巧克力饼时才会显现出来。

没有一家开发商、服务或公司能够对可持续性产生实质性影响。采用锈迹就像回收;只有我们都参与,它才会产生影响。为了实现广泛的采用,我们必须发展开发者社区。

Rust开发者社区在过去两年中增长最快,但根据历史趋势,我们知道,在过去12个月加入Rust社区的50万开发者中,大多数人还不精通该语言。我们在Rust developer体验方面还有一些工作要做。

提出的问题是哪种开发者体验?与构建数据库服务的工程师或提供零售网站的工程师相比,开发Linux内核的工程师有着截然不同的理想开发体验。我们可以通过外观识别用户角色

......