Amazon Prime Video的Rust革命:从C++到WebAssembly的UI重构完整访谈录

104 阅读1小时+

本文首发公众号 猩猩程序员 欢迎关注

wechat_2025-07-02_094755_557.png

播客介绍

欢迎收听Rust生产环境播客第五季,这是一个关于使用Rust塑造基础设施未来的公司的播客。我是来自Corrode的Matias Endler,今天我们与Prime Video的首席工程师Alexandra En进行了对话,讨论在Rust中构建现代用户界面的话题。

第一部分:背景介绍

主持人: Alex,非常感谢您抽出时间。您能介绍一下自己和您工作的公司吗?

Alex: 你好。感谢邀请我参加这个节目,这非常有趣。我是Alex,是Prime Video伦敦的首席工程师。我在那里工作了大约八年,实际上快九年了。在此之前,我在育碧做视频游戏、游戏引擎等相关工作。现在,正如我所说,我在Prime Video工作,负责您在客厅设备上使用的Prime Video应用。我们在那里大量使用Rust,这就是我在这里的原因。

主持人: 当您说您做视频游戏时,这意味着您也在那时使用Rust,还是使用其他语言?

Alex: 不,那时是C++和C,主要用于Unity,但主要是在育碧使用C++。我不知道他们现在使用什么。我在2016年离开,在2017年或2018年了解到Rust,我想是2017年。所以我甚至不知道Rust的存在。实际上,在很长一段时间里我都忽略了它,以为它是一种垃圾回收语言。但后来我在YouTube上看到一个人用Rust做演示场景类型的东西,这些是超小的可执行文件,可以做艺术、漂亮的视觉效果和音乐。所以我想,"哦,等等。它没有垃圾回收器。那么他们是如何做到他们一直在说的内存魔法的?"这就是我开始接触它的方式,然后在开始时用它做一些小型模拟器,从那时起我仍在业余时间用Rust构建游戏。我会说这是我在工作之外的大型Rust项目,也是我接触它的方式。

第二部分:从C++转向Rust的经历

主持人: 这很有趣,因为您来自C++背景,我认为很多听众也有相同的背景。那么最终是什么说服了您使用Rust?仅仅是因为它没有垃圾回收器,还是您在某个时候也开始喜欢这门语言?

Alex: 我并不反对C++以外的东西。我只是讨厌C++的构建系统。它们只在Windows上工作。我只能使用Visual Studio。使用CMake总是很痛苦。所以当我看到Rust只需要cargo new就能工作时,这对我来说是令人震惊的。我的意思是,来自JavaScript和其他语言的人会说,是的,我们已经这样做了很多年了。你在说什么?但对于一个C++程序员来说,能够执行cargo new或cargo run并且一切都能正常工作,这在当时对我来说简直是令人震惊的。然后我开始喜欢语言的一些部分,比如枚举等等。我真的非常喜欢这些。但是,构建系统简直是神奇的。

我仍然记得第一次在YouTube上观看这个叫Ferris的人,他在构建一些演示场景的东西,他开始一个新项目——他在构建N64模拟器,我相信——他用Cargo New开始一个新项目,然后Cargo run。我想,这是怎么回事?这太酷了。这就是我接触它的方式。

主持人: 向Ferris致敬。他也是我接触Rust时观看的第一批流媒体主播之一,他真的很棒。我想每个人都应该在YouTube上观看他的内容。它仍然在那里。我甚至会说被严重低估了,因为他真的从头开始构建了一个N64模拟器。不确定他走了多远,但这个想法本身就很棒,对吧?是的,我希望他能再次做更多的Rust内容。是的。是的,我们应该发起请愿让他回来,或者至少在播客上邀请他。他是个好人。

但在C++中,您有Conan或包管理器之类的东西。我不熟悉C++包管理的状态。您能启发我们吗?

Alex: 我们没有——我从未使用过任何这些。我认为它们在当时在游戏开发者中并不那么流行。所以我使用的只是原始的Visual Studio,然后创建项目,然后进行所有设置,实际上我和一些朋友制作了一个游戏,我们将其移植到Linux,我们都没有——我们只是直接使用make文件,甚至不是CMake。只是将您的文件放在make文件中的正确位置,然后它就会工作。但我不熟悉这个。我从未使用过Conan。每当我提到构建系统时,人们总是提起它,但我从未尝试过,我不认为它们当时对Windows支持得很好。我不确定状态如何。

主要是我是Windows开发者。我从来没有——只是最近我买了一台Mac。

主持人: 我认为关于Conan不是C++官方标准的一部分,或者说,它是一个独立的项目,这一点值得说明。我想独立有一些好处,但实际上,对于像包管理器这样核心的东西,在2025年,将其作为您安装的正常生态系统、运行时的一部分真的很有益。

Alex: 是的。我会说这使得启动体验更加顺畅。所以这有点遗憾,但是,我自2018年以来就没有写过C++,所以我现在很高兴。因为我所有的副项目过去都是用C++,比如各种游戏迷你游戏引擎等等。所以现在我用Rust做这些,现在我在工作中也使用Rust。

第三部分:代码审查和内存管理

主持人: 作为工作的一部分,您可能也会审查很多代码。自从您从C++转向Rust以来,审查过程发生了怎样的变化?

Alex: 这实际上真的——您可能知道,因为您采访过其他人,但我可以告诉您,我在代码审查时放松了很多。例如,我们团队中仍然有C++代码,用于我们在设备上部署的东西。我们有一个抽象系统的迷你层。所以那是用C++编写的,带有虚拟机和UI后来使用的所有东西。所以那是C++,然后在Rust代码中,就像只关注代码是否在做它应该做的事情,而不是您在对这个内存做什么?它来自哪里?它要去哪里?即使使用智能指针或唯一指针,作为新手也很容易搬起石头砸自己的脚。对于审查代码来说,这绝对更轻松。我认为在内存访问方面编写正确的代码要容易得多。这很简单。

现在我要说的一件事,这对Rust采用帮助很大,就是它不需要多年的经验。例如,如果我要为我现在使用Rust的相同事情出于性能原因提议C++,那将非常困难——让人们接受C++是如此困难。所以在大学里我学了C和C++,但今天情况不再如此。他们中很少有人,新毕业生甚至很少做C++。所以让他们上手真的很难。这需要很多时间。而使用Rust,这要容易得多。基本上在Prime Video切换到Rust的团队是从JavaScript切换到Rust的。这很好。我的意思是,这是一门新语言。它有一些上手过程,但想象一下让只知道JavaScript和Java的人切换到Rust再到C++。这只会到处都是崩溃。这是必然的。所以我会说,对于了解其他语言(不是C++)的团队的采用,让新人甚至新毕业生或专家上手要容易得多。

主持人: 总结一下审查C++代码和Rust代码之间的区别是,在C++中您需要非常小心内存的去向,内存管理在审查过程中更加核心,而在Rust中更多的是关于业务逻辑,更多的是关于数据流,但不是在系统级别,而是在业务逻辑级别。

Alex: 是的,您只是在验证这段代码是否在实现它应该实现的功能,而不是在低级别上您在对这个内存做什么?访问它是否安全,您在哪里访问它,您是否在线程之间奇怪地共享它等等。我过去学习C++的主要问题是有太多隐藏的知识。有太多关于这门语言您需要知道的不成文的东西。这是一门您需要学习的大语言。而在Rust中,很多东西都有很好的文档,是的,有学习曲线,但在此之后您有相当好的文档。您有编译器帮助您,语言感觉仍然更小。

是的。C++的问题是每个人都选择自己的风格,您知道,然后语言中有各种各样的部分,哦,不要使用那个,但它在那里。作为新手,您不知道什么不应该碰。指针仍然在那里。像原始指针,它们无处不在。它们只是,很容易就访问它们来绕过某些可能会捕获的东西。所以像唯一指针。哦,让我只是让我从这个唯一指针中抓取指针并做我的事情。或者其他什么,它只是可能意外地将其共享到其他地方,然后将其保存在其他地方,这就是您很容易得到释放后使用的方式。所以这就是问题。而像Rust这样的新语言,它们没有这种每个人都需要选择子集的问题。它们只是使用整个语言都很好。整个功能实现得更加连贯。所以我认为这是一个大问题。

第四部分:语言演进和设计哲学

主持人: 嗯,有人可能会争论说,C++有所有这些注意事项的一个主要原因是它是一种历史上随时间增长的语言,并且仍然与C兼容。我实际上不确定这是否仍然是真的,或者这现在是否是一个都市传说。我想听听您对此的看法。其次,我认为当您在C++中构建更大的系统时,您会遇到所有这些真正棘手的数据管理问题,因为这会在某种程度上困扰您并在以后咬您。它不会在开始时咬您,通常不会在编译时。所以您处于这样一种情况,即以后您有一个更大的C++代码库,然后突然这些问题出现了。

Alex: 是的,我认为一个方面肯定是它随时间增长,甚至多线程编程在我上大学或刚进入大学时变得流行,当时像Herb Sutter和那些人说没有免费的午餐。他们在写这些文章,所以这是一种语言,只是无法预测计算如何发展以及多线程和所有这些东西。所以我认为历史绝对起了作用。这不像他们实现错了。他们只是不知道。所以像多线程直到语言历史的后期才在这种规模上成为一件事。所以C++在那里有难以学习的教训。而Rust已经带着这种后见之明的好处和随时间发生的知识而来。

所以我认为它已经有了更多。所以当他们设计Rust时,我假设他们对今天的计算是什么样子有更多的知识?其他东西的常见问题是什么?让我们以破坏性的方式修复这些,因为它与C++没有任何向后兼容性,对吧?他们没有那个约束,所以我认为他们做得非常好,Rust设计师和在那里贡献的人。C++一直在尝试做所有这些事情,有各种努力,但老实说,我认为他们可能应该停止向语言添加东西,就这样。

我们一直在,您知道,您一直在添加,他们最近添加了像选项或结果类型,它看起来就是如此丑陋。不明白人们如何能批评Rust看起来丑陋。这些写C的人,然后您看C++和C,天哪,发生了什么?老实说,当我开始时它并没有那么糟糕,C++11。好的,那很好。那是一门好语言。只是停止向其添加东西。

主持人: 您如何看待像Bjarne这样的人试图使C++更安全的所有这些最近的安全努力?这有什么进展吗?

Alex: 我没有跟上那些的最新情况。我知道有一些努力。Herb也是微软的人,我想是Herb Sutter。他也有一些想法,甚至有某种智能的,但我不了解那里发生了什么的最新情况,总的来说,关于我工作领域的安全性,威胁模型是这样的,您没有,有其他性能绝对是首要任务而不是安全性。所以对于视频游戏引擎,例如,您更关心那个而不是安全性,特别是对于单人游戏,您不会真正与外部交互。

主持人: 您认为性能和安全性总是相冲突的,还是Rust证明了您可以两者兼得?

Alex: 不,您可以两者兼得,我认为在好的C++中您也可以两者兼得。今天从我所看到的,我们使用的基线库是用C的。OpenSSL和那些东西。Curl,每个人基本上都在各处使用curl,安全性在那里超级重要。所以我认为您可以在两种语言中都得到它,但需要不同程度的努力。它们不相冲突,但对于某些语言,它们绝对比其他语言需要更多的努力。

主持人: 现在,我不确定您是否仍然写任何C++,但如果是这样,或者即使您现在只是阅读C++代码,您处理语言的方式是否发生了变化,编写风格或您认为好的C++是什么?

Alex: 所以我认为当我学习Rust时帮助我的一件事是它某种程度上形式化了您应该思考内存和内存访问模式的方式。所以我不认为我曾经用谁以可变方式访问这些数据的想法审查C++代码。我脑子里就没有这个概念。我主要看的是您是否在正确的时间释放了它,这可能是生命周期的模糊概念,但不像Rust使其那样正式。所以它绝对给了我至少一些词汇和更结构化的思考方式来捕获那些问题,当我审查代码时,因为我的意思是在开始时我只是在家里为我的副项目和激情项目使用Rust。所以然后当我去工作时,我在写C++,它让我想得更多一点,比如,哦,这里的访问顺序是什么?这个东西活多长时间?它给您一些词汇。所以即使您写C++,我认为它使您成为更好的C++程序员。

第五部分:在Prime Video的Rust实践

主持人: 是的。您在Prime Video用Rust做了什么?

Alex: 所以我只是一个慢慢用Rust重写东西的人,最近几乎完成了整个应用程序的重写。所以基本上我开始工作在——我工作的团队是客户端团队,这有点特殊,因为我们在客厅设备上工作。所以基本上我们Prime Video的工作方式是我们有一个应用程序,无论性能如何都会在所有这些设备上运行。所以它可能是所有的游戏机、所有的电视、机顶盒、流媒体棒,它们都运行相同的应用程序,该应用程序有一个小的C++层,过去在顶部有一个JavaScript和React层。

基本上我的工作从那个C++层开始,然后我继续开始用Rust和WebAssembly重写JavaScript部分的一些部分。所以我们不再通过空中传输JavaScript包,现在我们发送WebAssembly包,人们下载它,我们在设备上有一个WebAssembly虚拟机来运行该代码,主要是出于性能原因。

但这是我做的很多工作。所以最近我们从UI低级位开始,例如只是场景管理、动画等等。那些变成了Rust,四年、五年前,我不记得了,也许四年。我的时间线有点混乱。

但我们从更基础的级别开始。然后今天我们甚至用Rust编写了我们自己的UI SDK来替换React部分。现在我们的UI客户端工程师,前端等价物,正在将Rust作为他们的日常工作写了大约一年左右。

所以这个应用程序已经部署在很多设备上,但您可以想象这是相当多的,因为它运行在所有的游戏机、所有您能想到的机顶盒和电视上,三星、LG、索尼,一切。

所以是的,我猜它也运行在一些游戏机上,比如PlayStation 4和5以及Xbox我猜。

主持人: 是的,游戏机PS4、5。嗯,所有的Xbox,Xbox One、Xbox One S,现在有很多,但是是的。嗯,所以一些人甚至可能在某个地方有您的应用程序的多个部署。我不会感到惊讶,因为至少您有一台电视,如果您在2017年左右购买的,它可能是这些有应用程序的电视之一。所以,它会有私人应用程序,因为它们有时甚至预装,对吧?

Alex: 是的。是的。所以这是问题之一,因为正如我所说,这些设备中的硬件,特别是在更便宜的电视或机顶盒上,并不是超级强大,即使在流媒体棒上,它们由USB供电,对吧?所以您不能有疯狂好的硬件,因为它只是USB连接能提供的任何东西。所以基本上理想情况下我们会将我们的代码写成像C或Rust这样的东西,从一开始。让我们说Rust不在桌面上,但我们会用C++做一切,并拥有最好的性能,因为我们已经为本机层拥有了它。问题是在这些设备上,您没有应用商店。所以有时您的应用程序与固件更新一起提供。有时这是一个相当手动的过程。所以这就是为什么我们更多地转向JavaScript和React,这样我们就可以继续向客户发送错误修复和更新。结果,性能并不出色,正如您可以想象的那样,我们必须投入大量精力来优化它,即使如此也很困难。所以,Rust和WebAssembly在性能方面帮助很大,它是您仍然可以发送和下载的代码,并且比JavaScript代码具有更好的性能,因为如果您想象今天的JavaScript,您可能想象它在笔记本电脑或手机或其他您启用了JIT的地方,但在这些设备上,您甚至可能没有足够的内存来启用像V8或其他的JIT虚拟机。所以非JIT的JavaScript就是如此缓慢。大多数人不知道这种痛苦。所以是的。

主持人: 是的,这是一件事。另一件事是我甚至不确定这些设备上的垃圾回收。它的工作效率如何,因为最终您可能会耗尽内存或者只是非常滞后。当您使用它更长时间时它会变慢。您遇到过这种情况吗?

Alex: 是的。所以我们触发。所以因为垃圾回收在非JIT的JavaScript中是如此大的问题,如果我们有动画播放,我们可以禁用垃圾回收,然后我们在知道安全时手动调用VM上的GC来做一点停顿,比如您空闲或其他什么。所以这对我们来说也是一个巨大的问题,因为这些设备运行很长时间,有时人们让它们开着几个小时,甚至有时几天。您不能真的只是,您知道,关闭它然后重新启动。这不是一个选择。

嗯,我们在这种情况下会这样做。这实际上是更好的体验,顺便说一下,比我们可能会得到的。但因为您有异常,如果发生意外的事情,您可以只是捕获它并重新启动整个应用程序。我们在转换到Rust时失去了这个。所以我有点想念一个巨大的try catch类型的情况,特别是在WebAssembly中,您没有堆栈展开,您不能做同样的事情。

在原始Rust中,您可以展开堆栈。这是真的。您可以技术上panic或抛出错误,然后在那上面展开,对吧?或者如果您有panic,如果您想要的话您可以处理它。但如果您跨越Rust到WebAssembly边界,这就是事情变得真正困难的地方。

主持人: 是的。所以在WebAssembly中,今天这是不可能的。所以我们失去了一些功能,我会说。但至少它总的来说非常稳定。但如果您确实有panic,这是一个非常不愉快的体验。实际上,我要说的一件事,在Rust中编写无panic代码是极其困难的,因为您不能完全知道何时会发生panic。它可能在您的依赖项之一中。它可能在任何地方。这不像您不能对此做任何事情。所以其中一个panic来了,我记得因为我们因为这个边缘情况而被叫醒,某个地方与第三方库的工作方式有关。当第三方库检测到您不应该以某种方式调用某些东西时。它会panic。就像这是不正确的。但然后客户就没有应用程序了,伙计。您做了什么?

所以然后我们必须修复那个并打补丁,嗯,返回一个结果,因为人们有时附加到事物上的正确性程度,我觉得它们有时有点太多,我们可以更宽容一点,返回一个结果,但不要因为在某个深层库的某个地方您发现一些有点可疑的输入而关闭整个东西。

这是一个有趣的观点,因为我认为这是嵌入式系统的一个常见问题,您真的不希望系统崩溃。您希望它继续运行,即使它可能处于某种降级状态。

主持人: 是的,这是一个很好的观点。我想这也是为什么您需要真正了解您正在重写的系统的问题。您不能只是说,"哦,我们要用Rust重写这个,它会更好。"您需要了解现有系统的所有权衡。

Alex: 是的,绝对是这样。我认为这是一个非常重要的观点。您不能只是说,"让我们用Rust重写一切,因为它更好。"您需要了解您正在解决的问题。在我们的情况下,我们有性能问题,我们有内存问题,我们有这些设备上的限制。所以Rust和WebAssembly对我们来说是有意义的。但您需要了解权衡。

我们失去了一些东西。我们失去了那个巨大的try-catch。我们失去了一些灵活性。但我们获得了性能,我们获得了更好的内存管理,我们获得了更好的并发性。所以这是一个权衡。

第六部分:技术架构和实现策略

主持人: 让我们谈谈技术细节。您如何处理从JavaScript/React到Rust/WebAssembly的过渡?这是一个大爆炸式的重写还是渐进式的?

Alex: 这绝对是渐进式的。我们从小的部分开始,比如动画和场景管理。然后我们逐渐扩展到更复杂的UI组件。我们不能做大爆炸式的重写,因为我们有数百万用户在使用这个应用程序,我们不能冒险破坏他们的体验。

所以我们采用了一种方法,我们一次替换一个页面。我们从最简单的页面开始,比如用户配置文件页面,然后逐渐转向更复杂的页面,比如主页和搜索页面。

这种方法的好处是我们可以在每一步都测试和验证,确保新的Rust实现与旧的JavaScript实现具有相同的功能和性能。实际上,在大多数情况下,性能要好得多。

主持人: 您能量化一下性能改进吗?

Alex: 是的,我们看到了显著的改进。例如,在输入延迟方面,我们从最差设备上的400多毫秒降低到30毫秒。这主要是因为我们简化了逻辑,Rust的性能也起到了作用。

我们还看到了内存使用的改进,尽管最初内存使用实际上更高,因为我们同时运行JavaScript和Rust。但随着我们逐步淘汰JavaScript,内存使用量预计会下降。

主持人: 您如何处理JavaScript和WebAssembly之间的通信?

Alex: 我们使用消息传递在JavaScript和WebAssembly虚拟机之间进行同步和状态一致性。这避免了中断任何一个世界,并简化了实现。

基本上,我们有一个消息队列系统,JavaScript可以向WebAssembly发送消息,反之亦然。这允许我们保持两个系统之间的状态同步,而不需要复杂的共享内存方案。

主持人: 在移植过程中,您是否尝试"修复"原始JavaScript代码中的错误或问题?

Alex: 不,这是一个重要的教训。我们学会了移植现有行为,包括错误,而不是试图在翻译到Rust等新语言时"修复"事情。依赖关系通常依赖于原始的、有时是"错误的"行为。

如果您试图在移植过程中修复错误,您可能会破坏依赖于该行为的其他部分。所以我们的方法是首先进行一对一的移植,然后在单独的步骤中修复错误。

主持人: 您如何处理不支持WebAssembly的旧设备?

Alex: 我们继续为不支持WebAssembly的旧设备维护JavaScript页面。这意味着我们需要维护两个代码库一段时间,但这是确保所有用户都能继续使用应用程序的必要权衡。

随着时间的推移,随着旧设备被淘汰,我们可以逐步减少对JavaScript版本的支持。

第七部分:团队规模和代码库

主持人: 您的团队有多大?代码库有多大?

Alex: 我们大约有100个贡献者,代码库大约有5万到10万行代码。我们大量使用宏来实现类似JSX的UI组合。

这可能听起来很多,但考虑到我们支持的设备数量和功能的复杂性,这实际上是相当合理的。宏帮助我们保持代码的简洁和可维护性。

主持人: 前端工程师如何在不深入了解Rust的情况下使用Rust UI?

Alex: 我们通过放宽数据复制和使用像Leptos这样的框架来实现这一点,这些框架提供了熟悉的响应式编程模型。

Leptos特别有用,因为它提供了类似于React的编程模型,但是用Rust实现。这意味着来自JavaScript/React背景的开发人员可以相对容易地过渡到Rust UI开发。

我们还投资了工具和文档,使前端工程师能够专注于UI逻辑,而不必担心Rust的低级细节。

第八部分:游戏引擎架构和异步编程

主持人: 您提到了游戏引擎。您的UI引擎架构与游戏引擎有相似之处吗?

Alex: 是的,我们使用实体组件系统(ECS),就像游戏开发一样。UI元素被视为具有附加组件和行为系统的实体,类似于游戏开发。

这种架构的好处是它非常灵活和可扩展。您可以轻松地添加新的组件和系统,而不需要修改现有的代码。这对于像我们这样的大型代码库特别有用。

主持人: 您如何处理异步编程?

Alex: 我们后来在Rust UI中集成了异步编程(async/await),这在传统游戏开发中不太常见,但对于经常与后端服务交互的UI应用程序至关重要。

最初我们避免使用async,因为它的复杂性,但最终采用了"延迟组件"来处理像在获取数据时显示加载指示器这样的场景。我们强调包装器方法而不是使所有UI代码都异步。

这种方法允许我们在需要时使用异步功能,但保持大部分UI代码同步和简单。

第九部分:WebAssembly开发和挑战

主持人: Prime Video参与WebAssembly开发吗?

Alex: 是的,我们参与了WebAssembly的微运行时和线程工作组。我们面临着由于向后兼容性问题和管道复杂性而导致的新WebAssembly功能(如SIMD和线程)的挑战。

我们还参与了关于WebAssembly中垃圾回收和panic处理的持续讨论,突出了不同用例(浏览器与物联网)和不同需求。

这些讨论很重要,因为WebAssembly正在发展成为一个在许多不同环境中使用的平台,每个环境都有自己的需求和约束。

第十部分:团队培训和招聘

主持人: 您如何培训团队使用Rust?

Alex: 我们强调从小型、自包含的项目开始,专注于性能重要的领域(如流畅的动画),并倡导更渐进的采用曲线来管理新开发人员的涌入。

我们发现最好的方法是让人们在实际项目中学习Rust,而不是只是阅读书籍或做教程。当然,这些也很重要,但实际经验是无可替代的。

主持人: 您如何招聘Rust工程师?

Alex: 我们不测试特定的语言技能,而是测试学习意愿。我们发现,愿意学习的优秀工程师通常可以很快掌握Rust。

我们更关注候选人的问题解决能力、学习能力和对技术的热情,而不是他们是否已经知道Rust。Rust可以学习,但这些基本技能更难培养。

主持人: 您对Rust社区有什么看法?

Alex: Rust社区的积极方面非常突出。人们非常乐于助人,文档质量很高,生态系统正在快速发展。

我希望看到Rust生态系统中构建速度和迭代时间的改进。这是我们仍然面临的一个挑战,特别是对于大型代码库。

但总的来说,Rust社区是我见过的最好的技术社区之一。人们真正关心代码质量、安全性和性能,这创造了一个非常积极的环境。

结语

主持人: Alex,非常感谢您分享这些见解。这对我们的听众来说非常有价值。

Alex: 谢谢您邀请我。这是一次很棒的对话,我希望这对考虑在生产环境中使用Rust的人有所帮助。


播客制作信息

主持人: 这就是今天的节目。如果您喜欢这个播客,请在您喜欢的播客平台上订阅和评分。您可以在我们的网站上找到更多剧集和资源。

制作: 本播客由Corrode制作。音频工程由[音频工程师姓名]完成。

联系方式: 如果您有问题或建议,请通过我们的网站或社交媒体联系我们。

下期预告: 下期我们将与另一位在生产环境中使用Rust的工程师对话,讨论Rust在不同领域的应用。

感谢收听!

主持人: 如果我开始这样的项目,我会担心我永远无法更新我的部署。一旦它在这个盒子上,它将永远留在那里。有时人们不会在他们的设备上做任何更新。所以它需要是完美的或至少非常接近健壮的。

这在进入时是一个担忧吗?可能您之前就已经有了这个问题,所以这不是一个新问题。

Alex: 是的,我们已经有了这个问题。我的意思是,我们下载的Rust代码作为WebAssembly包,所以这没有改变。这不会永远留在设备上。这只是每次您启动应用程序时,如果发布了新的应用程序,我们就下载一个新的应用程序,对吧?

在C++方面。我们这样做是为什么很多管理我们UI场景的低级代码,比如做动画、创建带有节点的场景树、节点的层次结构等等,最初都在JavaScript中。通常浏览器或其他UI引擎为了速度在C++中做这个。但因为我有那种恐惧,伙计,我在这里写的任何东西我们写的并且主要永远留在这里,这不完全正确,因为如果发生什么事情,您可以要求更新与合作伙伴合作,但这是一个非常昂贵耗时的过程,对吧?因为每个更新都会不同,它们繁殖得非常快。

所以我们通过最小化您放在设备上并且必须在那里的C++代码量来解决这个问题。但然后我们因为我们将其移动到JavaScript而遭受性能问题。但与此同时,我们很幸运,WebAssembly被发明了,我们可以采用该技术并部署它,然后通过空中传输Rust代码。所以

主持人: 现在很多人有一些Rust经验,甚至一些生产Rust经验,但他们从未真正编写过平台,因为对我来说,您在这里构建的听起来比人们定期接触的要基础得多。您对开始这样大项目的人有什么建议吗?或者您甚至会不同意并说,嗯,这不是真正的平台,因为我们仍然有下面的旧C++层,但我们只是用WebAssembly替换JavaScript,我们嗯

Alex: 对我们来说这很容易,因为我们有切换到JavaScript版本的备份,对吧?所以当我们做这个项目时,它总是作为实验开始,让我们看看会发生什么,它不完全是那样,但它有点作为研究项目开始,您有办法回到旧应用程序。我认为我要说的一件事是因为我们最终用我们自己的UI SDK替换了React,这是一个相当大的项目。我认为您是对的。这是一个巨大的,它不是基础性的,因为我们只有一个客户端,一个使用我们的应用程序,对吧?所以这不像我们是必须服务数十亿项目的React。

但我不认为您可以在不完全深入理解您想要替换的东西中的问题的情况下构建这些UI SDK。对吧?所以这对我们来说是一个8年的整体旅程,自从我在那里以来,可能更长,因为应用程序在我之前就存在了。您学到的教训对任何未来替换的成功都非常重要。所以我会非常谨慎地允许,例如,如果某个团队来找我,他们说他们想用Rust重写某些东西,我要测试他们的第一件事是您对当前系统的问题理解得有多深,或者您只是像我一样的粉丝,这很好,我显然很高兴当这些事情发生时,因为我喜欢这门语言,但我认为如果您想在这里成功,我会说真正真正重要的是深入深入理解以前东西的所有痛点和优势,对吧?因为这不像我们用Rust重写了一些JavaScript就更好了。有些东西更糟,比如我不能再panic了,这真的很难永远不panic。好的,所以在错误的点访问数组,就是这样。没有更多的应用程序。这在JavaScript中不会发生,您知道。所以这总是一个权衡。我会说

主持人: 这太真实了,因为您需要理解您来自哪里,您需要理解您的问题域。如果您没有那种知识,您就错过了移植到任何新语言(如Rust)的50%以上的优势。

很多人他们只是认为他们搬到了更绿的牧场,而实际上他们只是用另一个问题换了一个问题。

Alex: 这真的很真实,就像我们不是这样开始的,对吧?我们从只做我们知道Rust会做得很好的事情开始,因为我们已经知道我们在JavaScript中做得不好,那就是管理UI元素树。所以,我们将其从C++移动到JavaScript以获得可更新性。但我们知道那里的权衡。我们构建了它,我们想,"哦,天哪,这太慢了,但至少我们可以更新它。"所以当我们做出决定让我们保留React应用程序但将UI树的管理放在Rust和WebAssembly中的不同VM中,这两个东西通过某种消息总线通信时,这是一个相当容易的选择,从一个较小的项目开始,它有一个备份,您总是可以回到有效的东西,它给团队呼吸空间来进行研究并部署它,甚至没有数十亿团队协作。

这个。所以我们将UI树管理移动到Rust的初始事情,我认为是由七个人在七八个月的时间内完成的,但他们没有与其他团队互动,甚至不知道我们在他们下面切换了东西。所以这相当不错

当我们重写UI时,每个人都知道,因为没有其他方法,您影响了很多人,但至少您来自更有经验的,您已经在生产中部署过一次,您知道您在团队中有相当多的专家,所以这是一个更容易的销售

主持人: 我猜转换也更容易,因为您保留了React部分,然后您有这个到WebAssembly和Rust的桥梁。所以您不必替换整个东西。这不是从一开始就完全重写。这更多或少是渐进式采用。

Alex: 是的。是的。我们一次做一件事。基本上一次一个屏幕页面。是的。有趣的是您逐页进行,因为我想到的方式是您有点从动画开始,或者那不是入口点吗?

是的,我们从动画和那些东西开始,但页面仍然在React中,但当我们将页面移动到Rust时,一次一个页面,因为我们不想在同一个屏幕上同时有JavaScript代码改变屏幕和Rust代码改变屏幕。所以它们在引擎中的较低级别分离的方式,它是两个不同的世界。就像在ECS世界中,它们是完全独立的实体组件系统,对于那些世界。我们在那里使用实体组件系统,这是Bevy和那些引擎在Rust中使用的。它有点像2D引擎,但对我们来说它们是两个不同的独立世界。所以我们不想处理一件事,如果您这样做,这是非常有问题的,就是焦点管理。所以从Rust UI元素聚焦可能是React UI元素的东西是非常脆弱的,要跟踪所有那些东西。所以对我们来说一次移动整个页面更简单。它简化了事情,这有助于更快地交付它。

然后这意味着如果您使用应用程序,您可能在整个交互过程中多次在JavaScript和Rust之间切换。

主持人: 是的。是的。所以我们从三个页面开始,然后我们按使用和复杂性的顺序对它们进行排序。

这是亚马逊人指出的事情之一。当我们做这些大改变时,我们与角色、VP等审查很多文档,很多人有点担心从超级流畅的Rust页面到旧的JavaScript页面会看起来刺眼,我们如何确保它不像令人震惊,但最终还好。我的意思是这是不可避免的。

主持人: 您是从最慢的页面开始还是从最少使用的页面开始,策略是什么?

Alex: 嗯,我们从当您启动应用程序时开始,您看到用户配置文件。所以,首先我们替换那个配置文件页面,因为几个原因。它允许我们将一些代码投入生产。这不是一个复杂的页面,因为它就像三个按钮加上一点动画。

所以我们不需要构建太多UI引擎的部分。要记住的一件事是这个UI引擎并不存在,对吧?所以它是与应用页面同时开发的。所以,我们选择了一个没有太多小部件的东西,因为制作这种Rust中React等价物的UI引擎团队可以构建像按钮概念、焦点管理这样的东西,就这样。然后我们从那个配置文件页面开始,一旦您选择了它,您就会进入主应用页面,在那里您有所有的电影,我们称之为收藏页面。所以主应用页面是我们替换的第二个,然后从那里开始,那是最复杂的一个,然后从那里我们只是在播放的旅程中替换东西,基本上更多的是按复杂性加使用顺序,我会说。

主持人: 您在应用使用方面有任何指标吗?您看到恐慌数量激增或延迟下降了吗?

Alex: 我们看到延迟显著下降。特别是在最差设备上的输入延迟从大约400多毫秒下降到30毫秒。

所以输入延迟有了巨大的下降,主要是因为React工作的方式是一种非常复杂的方式,它做了很多工作来弄清楚事情,弄清楚树中的差异,布局也非常慢。所以我们在关键路径上简化了很多,同时允许某些可爱的功能,比如每个属性都可以被动画化等等。所以简化这些让我们在性能上获得了相当大的收益,再加上Rust就是Rust,WebAssembly只是比等效的JavaScript代码更快的选择。所以我会说这是两个优化。

一个是我们简化的逻辑,然后您从Rust获得基础层性能提升。

主持人: 我当然可以理解这一点,因为至少对我来说,当我使用这些应用程序中的任何一个时,输入感觉像是整个应用程序最慢的部分。比如您输入一个字母,它需要很长时间才能出现,这让我非常恼火。所以它一定感觉像是我的硬件的免费升级。

Alex: 人们确实给我发消息说他们知道我工作。所以就像"哦,你终于在我的电视上更新了它"。就像"是的"。

所以您绝对可以看出来,特别是因为这个推出通常是渐进的,因为我们也想监控它们是否影响业务指标,比如人们是否更多地使用应用程序,观看更多视频,这些实验运行时间更长。

所以不是每个人都同时得到它。

主持人: 人们只是基于速度注意到它,还是也有任何UI差异?您是同时处理更新UI,还是试图与旧版本一对一兼容?

Alex: 我们既不是。所以旧版本,JavaScript和Rust都是。所以Prime Video应用经历了重新设计,重新设计在JavaScript上发生,然后Rust部分只实现了新的外观。

所以它们都在进行某种重新设计,然后Rust来了,只是做了新的新东西。我们没有尝试做太多,除了我想在这里添加一些动画,但很少。所以您有一点,因为我们想展示布局动画。这些是以这样一种方式移动元素的动画,它需要您重新计算场景中其他元素的布局,只是为了展示它在Rust中的新UI引擎上真的很快。但那只是我想在一两个地方使用,或者我们试图让它们尽可能接近,因为那样它有点使所有的无效,您不能完全归因于"哦,为什么人们在Rust上更多地使用应用程序?"也许是因为动画,还是因为...很难找到原因。所以我们试图与JavaScript版本尽可能一对一。

主持人: 对。新版本有更好的性能,我假设它也使用更少的内存。这是否意味着它最终允许您对设备做更多事情,因为现在您有更多的空间。现在您可以更多地实验。

Alex: 在内存方面。我们实际上使用更多,因为我们仍然有JavaScript在同一个...就像我们没有删除JavaScript代码,如果我们在Rust中有它,因为如果我们需要切换到回退的JavaScript完整JavaScript体验,我们就把它保留在那里。所以总的来说,内存变得相当高,我会说,因为现在就像那里有两个应用程序。显然,当我们移植东西时,JS部分将被删除或最小化,用于诸如只是在那里有日志或其他什么的事情。

这是另一种您可以通过消息总线将东西推送到的自由线程,然后它可以做一些工作。例如,现在我们从JavaScript向我们的后端发送指标和日志。所以从Rust选项卡,我们收集它们,我们将它们发送到JavaScript。JavaScript将它们按摩成正确的JSON格式,然后不时报告事情。所以那一点可能不那么关键需要删除,但是的。

主持人: 所以在单独的线程中运行JavaScript和WebAssembly虚拟机很有趣。您如何处理这两个世界之间的同步和状态一致性?您提到了消息总线,也许一个或多个,我不知道。这是您通常处理内存同步的方式,还是有其他一些模式?

Alex: 我们不完全共享内存。嗯,您不能完全共享内存,因为WebAssembly内存模型的方式,所以我们只是在两个虚拟机之间发送消息,通过消息它们同步它们的状态。所以例如,假设您想同步历史堆栈,比如如果您按返回,那会去哪里?您只是发送一个消息说"嘿,JavaScript更新了"等等,然后它只是消息传递,就是这样,类似地JavaScript可以告诉Rust虚拟机,通常其中一个是源,另一个只是与源同步,所以只有一个真相源将其状态传播到只是跟随的虚拟机。

主持人: 是的,我想在这里使用消息总线的一个大优势,如果我错了请纠正我,是您避免中断任何一个世界。所以例如,如果WebAssembly线程做任何工作,它不需要立即对传入的消息做出反应,对吧?

Alex: 不。是的。而且它也比其他任何东西都更容易实现。所以您总是可以在您想要的时候拉取消息,每当您有时间处理它们时。确切地。所以您不...它们不是...显然如果处理消息需要很长时间,您就阻塞了那里的UI。所以它仍然有那些问题,但它给您一点回旋余地,关于您如何...是的。

主持人: 在您进行那个转换时,您修复了任何错误吗?您在JavaScript中发现了任何逻辑错误吗?任何您能够清理的不正确行为,甚至只是技术债务,以减少维护负担?

Alex: 没有,但我可以告诉您一件事,当我从JavaScript移植东西到Rust时我做了什么。我在UI中发现了一个有点可疑的地方,我用正确的方式做了它。我想这是为了帮助一些透明度被计算或者我不记得了,我破坏了应用程序。所以基本上然后我变得非常小心地告诉人们请维护JavaScript正在做的任何事情。那是Rust的基础。我们不是...我们不是在这里思考。我们正在移植它。让我们不要试图...真的很容易陷入"哦,让我用正确的方式做它"的陷阱,但然后您没有意识到您上面的其他东西依赖于它是错误的。这就是那个经典的模因,无论API在做什么就是API应该做的。是的,我们被那个咬了几次。特别是我,因为我对此感到如此自鸣得意。就像,"啊,看看这个愚蠢的东西。我修复了它。"然后就像,"嘿,Alex,您注意到这个东西根本不工作吗?"不。不。

所以,是的,我会说因为我重写了其中几个系统。我学到的教训之一就是用它拥有的任何行为移动它,尽量不要对此聪明。然后您可以...您可以稍后迭代事情。但是已经这些重写东西的项目我觉得它们比人们期望的时间更长,特别是因为它们通常相当乐观,就像"哦,UI树有什么复杂的,您知道它只是一个树有一些属性您更新它您遍历树您更新子项,如果您非常...您知道对此天真,您可以在一周内完成它",但然后事实证明它需要一年,然后事情中的每个小错误都需要被翻译,因为有依赖于那些错误的东西,人们为此放置了解决方法,然后如果您更改您的代码,它们的工作方式就不同了。所以,当我将它们翻译成新语言时,我只会保持事情原样,然后迭代它们。我会说我会建议不要试图修复任何东西。

主持人: 是的,我完全同意这一点,因为否则您会一次处理两个问题。

Alex: 所以我知道很多做同样事情的公司。他们开始移植旧逻辑,包括错误和一切,然后开始清理。这是在该领域工作的更有效的方式。特别是对于不知道的人...特别是对于不舒服或没有移植代码经验的人。这是您需要学习的技能。这是与从头编写代码不同的技能,因为您正在获取已经存在并在生产中运行的代码。是的。在这种情况下正确的是已经存在的行为,而不是您认为应该发生的事情。所以是的,如果您正在替换系统,我会说正确的含义会改变。

主持人: 是的。是的。说到旧行为,您仍然必须能够处理不支持WebAssembly的旧设备。您有两个代码库或两个单独的代码路径或某种回退吗?

Alex: 我们仍然有并行维护的JavaScript页面,我会说。它们没有获得所有新功能,比如所有新动画等等,但因为即使在全球低百分比下也有很大的...那些是很多客户,由于历史原因,他们仍然只获得JavaScript页面,因为我们还没有将Rust放在C++层上。所以我们仍然必须维护那些,我们正在努力某种回移植这个原生WebAssembly虚拟机,这样我们就可以允许它们运行WebAssembly,但现在它们都被维护。

主持人: 好的。所以这意味着我们现在在2025年。现在代码库有多大,团队规模是多少?

Alex: 所以团队规模大约是100个或更多贡献者到整个项目。我们有很多来自后端团队的人,他们只是想显示一些消息或类似的东西,他们必须写一点UI代码。所以这就是为什么数字如此之高,也许在代码库大小上低于100,000行代码,超过50行,我会说。我从来没有...我最近没有检查过。另外,检查起来有点困难,因为我们严重依赖宏,因为我们替换了React,我们想给人们这种类似JSX的组合UI体验。所以那扩展了很多。所以也许您写五行宏来组合一些UI元素,但然后由此生成的代码是相当重要的。所以很难说。是的。

主持人: 如果我要在那个系统中写一个组件,那会是什么感觉?即使我不是Rust开发者,对我来说会容易吗,还是会很特定?您提到了宏,它有点像JSX,作为JavaScript开发者我能理解吗,还是我需要先真正学习Rust?

Alex: 所以我认为在UI编程方面,所以如果您是前端类型的工程师,是的,您不需要学习太多Rust就能够编写代码。原因是我们在UI方面对复制数据非常宽松,我们将东西包装在RC指针和类似的东西中。所以它们不会遇到您在编写新Rust代码时通常必须处理的所有权问题。这不是超级优化的,但与JS相比无关紧要,无论如何都要快得多。所以我们有这个,我们曾经使用Leptos作为这个框架的效果和信号,这对知道React或Solid JS和那些类型的东西的人来说非常熟悉。所以在那个意义上它更容易一些。

我认为一般来说,当您从更高级别的语言转到Rust时,它更容易,因为当我编写React代码时,我不知道浏览器下面发生了什么。这个代码有时每次我点击按钮时被调用一次。这个其他代码是因为它不像您读代码,那就是它如何执行的。它总是它们去不同的地方。所以我认为在我们的框架中,如果您读代码,这就是事情如何发生的。我们只是扩展它,所以您不必手动写很多东西。但除了也许在效果和信号中没有魔法,它们仍然有点像魔法,因为它们是当您在另一个东西上设置值时被调用的函数。它如何知道调用函数?它只是有点,它不太直观,但对知道React的人来说是直观的,因为他们习惯了效果和这种类型的行为。对我来说,有这种"哦,这里发生了什么"是如此奇怪,结果发生的事情非常丑陋。它非常丑陋,但您知道这就是反应式UI工作的方式,对吧?

主持人: 因为您必须将那些东西移植到Rust,还是您找到了不同的方式来解决这个问题?

Alex: 所以那已经由Leptos完成了,有一些我们依赖的反应式框架。我们最终有点远离它,因为我们想优化某些东西,我认为开源项目正在朝着有点不同的方向发展。所以为了简单起见,我们必须在那里改变一些东西,但基本上有库做了这个,我认为那些类型的库推动了Rust UI一般可能的东西,并使前端工程师使用起来更愉快。

主持人: 您现在使用自己维护的Leptos分支吗,您指的是哪些库?

Alex: 所以有一些反应式的。我不记得名字。我们曾经使用Leptos,然后分叉了它,然后在上面写了我们自己的东西。是的。

主持人: 您提到的库,那些允许您在Rust中进行信号或事件处理的库。

Alex: 不,这是信号。所以Leptos基本上是信号、效果、类似的东西。它们也提供了一种声明式地做您的UI的方式,但我们没有使用那个。我们只使用了信号部分。在我们对话的很早期,我们谈到了游戏开发。我想知道那个设计有多少受到游戏开发的启发,或者您如何比较这两个世界?我理解这不是游戏,但感觉您有类似游戏的东西,比如对事件的反应、某种UI、某种事件循环,也许您可以比较这两个世界,您如何建模的?

Alex: 我会说基本上它在底层很像游戏引擎。所以现在Bevy普及了这个,但我们确实使用,我们也为我们所有的低级部分使用实体组件系统。所以虽然我们让前端工程师对Leptos类似的东西感到满意,有效果和信号以及这种反应式的UI编写方式,在底层它基本上或多或少是一个游戏引擎。所以它有实体组件系统。它有系统。每个UI元素都成为一个实体,我们根据它需要具有的行为将组件附加到该实体。然后我们有像焦点系统这样的系统,它查看每个可聚焦的实体,获取可聚焦组件,并根据您的输入做事情。所以它非常接近游戏引擎。

我们也许没有添加并且后来添加的一件事,我认为这使它与游戏引擎有点不同,是异步的东西,就像我们基本上根本不允许异步,因为您没有运行时,所以您不能对future做任何事情,对吧?所以我希望我们早点添加东西,这不是您通常在视频游戏中找到的概念,至少不是您今天在Rust中使用async和Tokio以及所有这些东西编写它的方式。它更像您在后端找到的东西,因为异步编程就像等待多个东西,而游戏做的是处理多个东西。所以它更像线程,您创建一些线程,您在那些线程上做工作而不是等待。所以那是后来添加的概念。

主持人: 所以我的理解是,使用实体组件系统,您想要做的是在同一个实体上并行工作,只是从不同角度看它,元素的某些方面,您只处理这些方面,但您确实并行处理它们,而在经典的,比如说I绑定系统中,您在它们进入时并发地处理事情,所以这是那两个世界碰撞的地方,您有异步或并发处理的事件,而您有点想并行更新UI,或者您想与您的实体并行更新所有这些属性。

Alex: 所以它们有点交互的地方是当您有等待网络调用的UI元素时。嗯。这在视频游戏中不是很常见,但在UI应用程序中非常常见,它们的大部分数据来自某个后端。嗯,在游戏中有一点,因为您从磁盘获取数据,您处理它,然后它显示在您的屏幕上,但异步编程对游戏开发者来说有点陌生,如这种承诺或您拉取的future的想法所理解的,我认为这不是在游戏中经常发生的事情。所以因为我们的UI引擎非常受后端响应驱动。我认为我们可以早点添加异步东西。

我个人,所以我是这个项目的技术负责人,我认为这有点是我的错,因为我没有完全理解异步,因为我认为异步代码非常有用,但阅读代码和对它如何执行有心理模型也非常困难,因此我决定好吧,让我们保持简单一点,不要有任何异步,然后给您一些回调,但事实证明,如果您不过度使用,实际上有些东西用异步会更简单。所以我们最终最近添加了它。所以现在您可以声明一个显示旋转器或其他东西的UI组件,当我们下载一些数据时,它将自动被其他东西替换。那是用异步完成的。现在我们称之为延迟组件。我认为它们在野外被称为。但对于那些场景,我认为这就是它与游戏引擎不同的地方。但除此之外,所有的图形、所有的事物遍历、我们拥有的所有实体组件系统都非常类似于游戏引擎。

主持人: 是的,我也可以看到解决那个问题的两种方法。一种是简单的方式,说您在组件周围有一个代理,组件本身完全是同步的,而围绕它的数据代理有点是异步的,然后传入它接收的数据。对吧?这是一种方式,另一种方式是说让我们完全拥抱异步,甚至在组件中做所有异步的事情,感觉您在某个时候从一个转到另一个,或者您在这方面改变了主意。

Alex: 我们没有。所以我们采用了您描述的第一个。所以基本上您有点将它包装到某个东西中,然后因为它是一个异步块,您可以编写您的代码,在网络调用上等待更好一点,创建UI组件,但然后UI本身将只是一个...它替换树中的某个东西,一旦它结束执行那个future,那就是正常代码。这是异步代码的困难,非常有点病毒式的。它只是到处传播,然后您需要与非异步代码有这些好的同步点,或者您要么全力以赴,到处都是异步。但我们没有那样做。我们只是允许某种包装器。它进入执行它的任务,在一天结束时,您将得到的UI代码将是正常的正常代码。它在某个时候从那个future中出来,通常一旦我们完成网络调用的处理或等待JavaScript或其他东西的某个消息总线。

主持人: 是的,在这种情况下,听起来保持较低级别的组件叶节点同步并在其周围有异步运行时更容易。

Alex: 是的。是的。因为最终在UI中很多模式都像设置超时。嗯。那些类型的任务也可以很容易地成为您然后不时运行的异步任务。那是另一个地方,我们...您只是作为UI工程师,您有这种创建函数并将其推入我们的执行器的方式,然后从中出来的任何东西可能稍后附加到UI树,但这有点像您得到的额外功能,而不是所有UI代码到处都是异步的。

主持人: 您从JavaScript移植了很多承诺到Rust吗,还是不是这种情况?

Alex: 有一些,因为我...处理网络的东西通常是那样的,用fetch然后做某事,然后您等待那些。我们现在有一种方式,您可以说您写一个异步函数。您随心所欲地等待,然后您获取那个future并通过我们的API发送给我们,这是添加任务,这是任务,然后我们在有时间时拉取它,通常每帧,但是的,这意味着您通常不使用vanilla future,您大部分时间有异步函数,然后您从外部拉取它们,但您不像使用vanilla JavaScript promise那样构建自己的future。

主持人: 不,不,不。是的,它是一个返回的异步函数。是的。

主持人: 您能够使用现在CPU的一些新功能吗,比如SIMD?

Alex: 所以我们确实与WebAssembly做了很多工作。所以我们为WebAssembly VM做贡献。这在GitHub上。它是一个WebAssembly微运行时。所以我们与社区以及WebAssembly工作组社区非常参与。所以我们在那里致力于向WebAssembly添加线程。

嗯。

SIMD是我们非常热衷的另一件事,那已经完成了。所以对于这些事情,有点...我们因为自己使用东西的渴望而受苦,因为您想使用最新的东西,您正在为它们做贡献,但然后它在我们这边创建了一个构建时决策,因为它们不是...WebAssembly字节码不是向后兼容的或保证向后兼容的,比如说。嗯,也许对于SIMD它不是。所以您需要启用功能,对于线程,您缺少一些函数。所以您可以让它工作,但它不是很好。所以我们对从我们的管道发出多少这些构建有点小心,因为我们不想过度复杂化我们的管道。所以这有点...这是一个棘手的事情。我们...它没有帮助那么多,因为我们没有做很多SIMD例如可以帮助我们的事情,也许如果我们重新架构我们的一些低级系统,但我们绝对在研究它并做贡献。所以是的,我们对那些感兴趣。

这绝对是一个热门的新空间,有很多事情在进行。我也知道现在WebAssembly中有一个关于垃圾收集的概念,或者至少有一个正在进行的工作草案。那也有点疯狂。我不确定是否有任何关于WebAssembly中panic处理的工作正在进行,这也会很有趣。对吧。

据我所知,在堆栈展开方面做了一些工作,这是我们在panic方面缺少的部分。有点像这两个...WebAssembly很有趣,因为有这两个或更多派系在研究它,它们有完全不同的用例。所以浏览器供应商,他们关心的东西与IoT空间的人关心的完全不同。所以我知道的没有在IoT设备上工作的人对垃圾收集感到兴奋,因为它只是额外的东西,对吧,您...它作为一个概念是有用的,当您谈论也许与...通信时它是有用的,但它只是...它是一个我认为对如此多的用例有用的项目,现在因为它而有点受苦,因为它被拉向所有这些不同的方向。所以也有使用WebAssembly的边缘计算类型的东西,那些情况有完全不同的硬件和功能要求,比如在IoT设备上使用它的人,甚至我们在电视上。我们有点在中间,因为它们不是IoT设备,但在我看来更简单更好。然后与Web浏览器有不同的观点。所以现在WebAssembly是这个热门的...所有这些不同领域解决方案的温床。我很好奇它将如何发展。

但是的,我会说与其他标准或事物相比,它绝对发展得相当快。好的。最后,您是一名首席工程师,您现在在与这些世界工作方面有很多经验,JavaScript、Rust、C++、WebAssembly。

我的问题是,您如何训练团队在Rust中高效工作而不失去任何动力?您的学习是什么?如果您现在重新开始,您会做什么不同的事情?您如何让团队从零到使用Rust生产?

这真的很困难。我会说的一件事,我发现成功的是从一个相当自包含的小项目开始对我们来说是关键的,这有两个原因。首先,您习惯了语言,您甚至习惯了人们在用Rust重写东西时不太考虑的事情。在亚马逊,我们在公司内部有相当好的生态系统。但如果您在一个没有那个生态系统可以依赖来部署一些Rust代码的公司,即使部署一些小的东西并保持它自包含也将为其他人将来更有生产力铺平道路。这就是为什么我认为从小项目开始是我绝对会倡导的。

我发现成功的另一件事是找到一个延迟或速度对您的客户很重要的地方。所以对我们来说,例如,拥有流畅的动画很重要,这就是第一个项目如何为我们开始的,只是做低级树管理,快速移动这些UI元素,然后人们支持它,因为我们想是的,当然流畅的动画,我们有什么可失去的,一些公司也许有不同的数学计算,但例如,如果您考虑在我们的规模上,七个工程师的团队一年不是一个疯狂的投资。

也许对其他公司来说是一两个人六个月,但它会有回报,对吧?如果您给人们时间,如果您有一个可以被Rust解决的问题,我会说通常围绕处理大量数据或做一些围绕那个的事情。这是一种让您的脚踏进门的简单方式。

如何大规模使用它然后有点更棘手,我认为这里例如我们...我没有...我们本可以做得更好,所以一旦我们完成了UI引擎的移植,即使那时团队也没有从100人开始,它从也许15人开始,我们增长和增长和增长,问题是在前两页之后我们如此成功,以至于我们想好吧,现在每个人您都在使用Rust,因为看看这个,它更酷,更快,更流畅,人们在家更多地使用它,更多地使用应用程序,他们观看更多东西,他们不放弃会话,您知道,我们到处看到提升。但问题是然后您有比能够在代码审查中帮助他们的人多得多的新人,然后它变得有点更困难。所以我认为他们有一个更渐进的采用曲线会更好,我会...这是您问我我会做得更好的事情。我会倡导我们在一次移动绝对所有东西上稍微踩刹车,只是迭代地交付,因为它有点像...我会说的这种事情,您提出像让我们将这个东西移动到Rust或让我们用Rust构建这个新东西等等或任何其他语言的事情有点像...赌一点您在您的组或同伴中拥有的信任。所以您获得一点信任,您发布一些东西,您获得更多信任,您...您再次赌您在新项目上积累的信任,这是在我看来作为技术专家您可以保持动力增长的方式。是的,我的意思是这也像...也许我在这里有幸存者偏见,但如果您做出正确的赌注,它相当...通常是好的。不要...如果您将所有信任都赌在一些从未发布的大型项目上,那么它将真的很困难。所以,我只是做更仔细的赌注,我知道我有相当好的交付机会。

在培训方面。实际上,这是我们仍在弄清楚的事情,因为人们学习如此不同。我对此有点无知,因为我是那个家伙,我不知道,读书,伙计们。有什么问题?只是一本书。我们有时间读它,但不是每个人都以同样的方式学习。所以我认为有一种更好的方式是...我们现在正在尝试做一些课程和类似的事情,更多地应用于我们的UI引擎。我们有一些文档,但它更像...它是您今天从同伴那里得到的知识。它不像哦,我在咨询文档并学习。它像一些有经验的家伙在代码审查中告诉我这更好,所以我现在这样做,然后我会告诉别人。所以这有点像...我不知道我们正在尝试通过一些课程和类似的事情以更有组织的方式传播的知识。

我会说在Rust特定情况下真正帮助我们的另一件事,特别是每个人都在快速移动,我们想快速发布,每个人都有时间写文档,对吧,但我们做得好的一件事是我们严重严重依赖于在Rust中编写示例的能力,所以example.rs,对吧,所以一切都有一个示例,所有UI元素,如果您...我们在我们的...如果您...人们通常使用VS Code或Zed,我将我们的launch JSON移植到Zed,但基本上我们有数百个示例,您可以从中选择运行并看到它们如何表现,在一个非常自包含的地方放一些断点,所以我认为这有助于新人入职,有像大量的示例,特别是对于更大的项目,所以您可以更容易地了解正在发生什么。所以这就是我会说的。但是的,从小开始,然后获得一点动力,做更多一点和更多一点绝对是方式。绝对结构化培训真的很重要。我想这也是为什么我们在这里。所以这有点好。

您在Rust工程师中寻找什么?您一定面试了很多。您如何知道他们,您知道,可以快速掌握语言?您在现实世界中看到的一些特征是什么,您可以判断人们是否会成功使用那种语言?

哦,这实际上很有趣,因为我们在招聘时不测试人们的语言技能。

所以在我看来,只要您不...一些人就是不喜欢这种语言,然后他们可以换团队或其他什么,但基本上我不认为它那么特殊。我认为整个Rust难学的事情。它只是关于这种语言的一个模因。我从来没有完全理解它,因为我一直试图学习C++十年。伙计,您知道,您不知道什么是困难。就像如果您告诉我Rust很难,就像试试C++。但所以在我看来,我认为这是一个已知问题。一般来说,所以在亚马逊,实际上我认为所有大型科技公司都不太测试特定语言技能,因为我认为假设您会弄清楚并学习等等。也假设您在那里逗留期间可能会使用多种语言。所以这不一定是...但显然如果您愿意学习那很重要,因为如果您...如果您抵制这种类型的变化,您不学习,它会...对您来说适应会更困难,对吧,也许一些人只是想写JavaScript,对吧,所以在那种情况下他们可以换团队或其他什么,就像大公司,但我会说总的来说我们对Rust培训和测试Rust技能不做任何特殊的事情。

这很聪明。是的,我完全理解。传统上,最后一个问题是,您对Rust社区的声明是什么?

嗯,首先,我对一切都非常非常满意。我们有如此出色的crate阵列可以学习。顺便说一下,这是其中一个社区,我真的想说这个,随着它的增长一直很友好。我从来没有在另一个变得更受欢迎的小众社区中注意到这一点。它通常有点退化,但与Rust社区的交互质量一直非常一致。所以我真的喜欢那个。

我希望我们在生态系统中更多关注的一件事是构建速度,就像迭代时间,只是把那些降下来。我认为现在我们或多或少接受了Rust编译会更慢或其他什么。但我认为在其他语言中有例子,人们已经得到了很好的结果,比如Zig正在构建速度和迭代时间上推进很多。我认为如果我们可以在我们的代码中超快地迭代,我们都会赢。就像按您按的任何按钮来运行您的代码。如果那是像2秒,它就是神奇的。一旦它超过某个阈值,我的生产力就...我会分心。所以我会大量工作并投资于...如果我像...如果我有权力投资Rust社区中的任何东西。我会说这将是投资迭代时间和构建速度以减少它们的真正好地方。

谁知道也许在某个时候我们将使用cargo sick build来构建我们的ROS项目,因为现在有一个用于Rust的sick编译器后端。

是的,特别是对于您不需要LVM等的整个优化的调试代码。是的。

是的,我会喜欢那个。Alex,非常感谢您抽出时间。我真的很享受这次冷静和理智的对话。谢谢您的采访。

谢谢您。这很可爱。非常感谢邀请我。我喜欢它。

Rust production是Cor的播客。它由我Matias Endler主持,由Simon Breen制作。有关节目笔记、转录本,以及了解更多关于我们如何帮助您的公司充分利用Rust的信息,请访问corro.dev。

感谢收听Rust in Production。