我们在将近一年前宣布了字节码联盟,从那时起它就是…。相当一年的😬。
虽然今年的2020年让我们在某些方面放慢了脚步,但我们在其他方面也取得了很大进展。
既然我们已经适应了新常态,我们就在各条战线上加速前进。但在此之前,我们想分享一些我们迄今取得的成就的亮点。
我们的目标是将WebAssembly从编译单片应用程序的编译目标发展到组成应用程序的模块化生态系统。
在我们这样做的同时,我们有机会解决软件开发方式中的许多长期存在的问题。例如,我们可以让您的应用程序更安全地使用不是您自己编写的依赖项。
这就是纳米过程模型如此重要的原因。这是必要的范式转换,使开发人员能够保护自己不受这些问题的影响。
您可以将WASI视为主机和WebAssembly模块相互通信的方式。
您可以将模块链接视为两个WebAssembly模块相互通信的方式。
在这两种情况下,双方通常都是用不同的源语言编写的。这意味着它们可能以不同的方式表示资源的值和句柄。基本上,他们说外语。
接口类型就像引擎用来帮助它们通信的外语词典。
注意:字节码联盟不托管规范。当BA成员驾驶下面提到的规格时,他们是与W3CWebAssembly CG中的其他人合作做到这一点的。字节码联盟项目包括这些规范的实现。
当我们介绍WASI时,我们将其与POSIX和其他系统接口进行了比较。不过,这有点过于简单化了。
虽然WASI的目标确实是提供一组标准化模块来提供这些低级系统接口操作,但我们也打算为专门的高级主机API标准化模块。
对于底层系统接口层,工作重点一直放在实现质量上。
在规范方面,这一直在识别和解决规范的跨平台可实现性问题。这方面的一个例子是WASI-Socket API(最近在Wasmtime中建立了原型)。在本例中,对话的中心是将基于功能的安全性应用于套接字处理的正确方式。
在实现方面,我们做了大量工作来提高实现的安全性和可靠性。这其中的一部分是开发强大的模糊措施(我们将在下面进行更多描述)。
我们做的另一件事是将安全关键操作分解到一个专用库CAP-STD中。它是一个跨平台库,以面向功能的方式提供了Rust标准库的大部分功能。这使我们能够完全专注于在所有平台上正确处理这些安全关键型基础。下一步,我们将在WASI实现中使用CAP-STD。
对于专门的更高级别的主机API,已经就全新API模块的提案进行了激动人心的工作。
WASI-nn就是一个很好的例子,它是神经网络的标准化接口。这很有用,因为经过训练的机器学习模型通常部署在具有不同架构和操作系统的各种不同设备上。使用wasi-nn,.wasm文件可以以可移植的方式执行诸如描述张量和执行推理请求之类的工作,而与底层的ISA和OS无关。
随着它们的发展,我们将在Wasmtime中实现所有这些功能。这样,人们就可以试用它们,现实世界中的使用情况也可以告知规范。
如果我们要有一个可重用代码的生态系统,我们需要一种将模块链接在一起的好方法。
现在,您可以使用主机API将模块链接在一起。例如,在Web上,您可以将一组WebAssembly.instantiate调用串在一起,以便将一组模块链接在一起。在Wasmtime中,您可以使用链接器API。
但是这种命令式风格也有一些缺点,包括它相当笨拙,速度不是很快,并且需要宿主包含某种类型的垃圾或循环收集器。
有了模块链接建议,链接就变成了声明性的。这意味着它更容易使用。这还意味着,即使在编译时,引擎也拥有有关模块如何相互连接的所有信息。这打开了许多潜在的优化和特性,并消除了循环的可能性。
目前,我们将重点放在加载时链接上,这将使模块能够提取公共库代码。就这一点而言,这项提案几乎是完整的。从长远来看,我们还可以添加运行时动态链接。
我们的下一步是完成原型实现,应该在接下来的几个月内完成。
接口类型现在可以谈论一组丰富的值。设计现在也更加高效,几乎在所有情况下都不需要值的中间副本。
虽然接口类型可以谈论值,但它们还不能谈论资源和缓冲区的句柄。这两种方法对于支持WASI和其他API都很重要,因为像文件这样的东西应该使用句柄,并且应该可以直接读取文件并将其写入缓冲区。
一旦这些特性就位,接口类型将拥有支持WASI和模块链接所需的一切,从而使它们能够以独立于源语言的方式谈论值和资源。因此,我们将继续研究W3C中的规范。
在实现上,我们已经为快速执行做好了准备。我们已经在Wasm核心中实现了接口类型所依赖的新特性,例如引用类型、多值和多内存支持。
我们还在开发使用接口类型的工具。目前,人们可以使用wasm-bindgen为JS代码创建绑定。在接下来的一年里,我们将直接向语言工具链添加对接口类型的支持,从Rust开始。
同时,对于想要在今天完成工作但又向前兼容的人来说,您可以使用WITX定义您的界面。你可以从Pat Hickey的这篇演讲或Radu Matei的这篇博客文章中了解到更多关于如何做到这一点的信息。
为了将纳米过程模型带给尽可能多的人,我们需要与尽可能多的语言集成。
如果您想要生成使用纳米进程模型的代码,您需要一个编译器:
为了帮助语言社区加速采用它们,我们已经开始构建wasm工具。这是其他编译器可以用来瞄准WebAssembly的一组标准工具。
这些都是我们在Wasmtime中使用的工具,所以当新的WebAssembly特性上线时,这里支持它们。例如,我们已经开始在这些工具中构建对模块链接的支持。
Wasmparser,它是WebAssembly文件的解析器。它相当便宜,因为它不做任何额外的分配,并且可以以流的方式进行解析。
Wasm打印机,它将.wasm二进制格式转换为.wat文本格式,这对调试和测试很有用。
Wat和wast,它们将.wat和.wast文本格式转换为二进制格式,这对于运行测试很有用(因为以文本格式维护测试更容易)。
WASM-Smith,它是一个测试用例生成器。它生成伪随机的wasm模块,保证是有效的wasm模块,我们将其用于模糊化。
明年我们将增加更多工具。例如,我们将在wasm-tools中托管Rust Interface Types工具包的与语言无关的部分,这将使编译为WebAssembly的语言更容易开始支持Interface类型。我们还计划与语言社区合作,在这些工具上线时将其集成起来。
如果您有一个完整的WebAssembly应用程序,则可以在Wasmtime等运行时中直接运行该应用程序。但有时,您只想在项目中运行一点WebAssembly。
例如,您可能正在编写一些Python代码,但是想要进行一些密集的计算。Python可能太慢,本机扩展可能太令人沮丧,无法移植使用,所以您可以使用WebAssembly模块。
随着新的纳米处理功能上线,它们将被添加到Wasmtime中。直到特性在我们维护的语言嵌入中公开,我们才认为特性开发完成。这意味着这些语言可以尽快运行最尖端的WebAssembly模块。
这也意味着这些语言社区不必想出自己的链接和绑定方式。它们可以仅仅依赖于WebAssembly标准,这使得一切都更具互操作性。
在去年,我们已经将我们维护的嵌入转换为使用标准的Wasm C API,并且我们保持Rust Embedding API和C API的同步更新。
我们以前说过,但建设这些基础是一项太大的任务,无法单独解决。这就是为什么有效的多方利益相关者协作如此重要的原因。
以下是我们在过去一年中所做的一些更改,以使协作变得更好。
Cranelift是许多运行时中使用的代码生成器,包括Wasmtime、Lucet和SpiderMonkey,以及其他项目中使用的代码生成器,例如Rust编译器的替代后端。它把wasm变成了机器代码。有了新的后端,我们可以更轻松地添加对新ISA的支持,并协作改进现有的ISA。
Cranelift之前的后端使用一个中间表示(IR)来表示所有内容。它还有一些晦涩难懂的抽象概念,很难使用。
新系统将流程分成两个阶段,增加了第二个特定于机器的IR。这样,每个IR都可以专门用于手头的任务。新系统还删除了模糊的抽象(您可以在用火杀死🔥错误中了解更多这方面的信息)。
我们还添加了一个名为Peepmal的新工具。有了这个工具,我们可以在代码仍然可移植的情况下(在我们到达第二个IR之前)应用窥视优化。我们正在使PEEPMIC变得更加灵活,这样我们也可以在第二阶段应用窥视孔优化,当IR是特定于机器的时候。
我们的目标是,任何不是控制流转换的东西都可以通过Peepma。有了这一点,我们在Cranelift中的一次性手写代码就会少得多,从而提高了可维护性。
它还有助于正确性:DSL Peepical的使用使得一些正确性问题变得不可能,而且比手写代码更容易推理。我们还计划增加对我们窥视孔优化的验证。这样,我们就可以检测到何时优化对所有输入都不正确。
为了实现Peepmal和WebAssembly沙箱的全部潜力,我们正在与学术研究人员合作。例如,我们正在与John Regehr和他的学生Jubi Teneja合作,通过与Souper集成来添加超级优化。多亏了加州大学圣地亚哥分校(UCSD)和赫尔姆霍兹信息安全中心(Helmholz Center For Information Security)的研究人员,我们现在有了一种很有希望的方法来减轻Cranelift的侧通道攻击。
如果您有来自许多组织的许多人添加新功能,您需要设置护栏,以确保他们在添加新功能的过程中不会破坏彼此的功能。
捕捉Edge case-y错误的一个非常好的方法是模糊。我们在建设一流的模糊基础设施上投入了大量的精力。我们甚至成为第一个接受Google的OSS-Fuzz连续模糊服务的主要用Rust编写的项目。从那时起,OSS-Fuzz已经发现了80-90个错误,否则可能不会发现这些错误。
我们模糊了WebAssembly的执行。如上所述,我们有wasm-Smith测试用例生成器,它非常擅长创建有趣的测试用例作为模糊的不同输入。我们还进行差分模糊处理,将优化后的结果与未优化时的结果进行比较,以确保得到相同的结果。我们做的是Peepma专用的毛发,外加各种其他的配置。
为了确保库中的调用正常工作,我们还对API进行了模糊处理。我们用模糊的工具来确保他们可以往返一切。如果fuzzer提供给我们的字节使用wasmparser成功地解析为wasm,那么我们将使用wasmprint打印它们,以确保它们成功打印为文本格式,然后我们将确保文本解析器可以解析结果。
在Cranelift中,我们不只是在入门IR级别进行模糊处理。我们还有第二个入口点,靠近管道的尽头,我们也可以在那里模糊不清。这使得命中寄存器分配器算法的所有转角情况变得容易得多。
为了确保我们继续拥有一流的毛发功能,我们制定了一条新规则:在您为其添加毛发功能之前,不会认为该功能已完成。
当然,如果你不知道某件事是如何运作的,就很难进行协作。为此,我们改进了文档和示例。
自从我们宣布英航以来,合并Lucet和Wasmtime就一直是我们的计划。该计划的执行将变得容易得多,因为Wasmtime团队正在快速行动!🎉。
Mozilla将继续有一个团队在Firefox中开发WebAssembly,专门专注于Web开发人员的需求。作为这项工作的一部分,他们将继续开发Cranelift代码生成器,许多项目都在使用该生成器,包括Firefox、Lucet和Wasmtime。
Fastly将赞助在Mozilla孵化的浏览器外项目的工作,包括Wasmtime和Wasi,我们期待着进一步扩大这项工作的范围。
这证明了字节码联盟的协作、多利益相关者的设置。我们在哪里工作并不重要,我们还在一起工作。
这个过程非常棒。但如果我们不把它送到用户手中,那就没有任何意义了。
Firefox对x86/x64的WebAssembly支持一直是同类中最好的。然而,由于体系结构的限制,它在ARM上的性能跟不上。Cranelift的启动是专门为了获得一个后端,它的架构可以在ARM和其他平台上工作,就像它在x86/x64上一样。
这现在正在结出硕果。在Arm64平台上的Firefox Nighly中,Cranelift现在默认用于WebAssembly内容,在x86/x64上使用它的工作也在进行中。
这是字节码联盟帮助加速整个生态系统的另一种方式。通过让我们的WebAssembly专家与ARM和英特尔的CPU架构专家合作,我们已经能够实现更好的设计,帮助我们更快地行动并获得更好的结果。
Fastly的目标一直是使开发人员能够将数据和应用程序移动到边缘。最近,他们使用WebAssembly朝着这个目标取得了一些巨大的进步。
他们是最早看到WebAssembly在服务器端潜力的公司之一。自那以后,他们已经将其开发成无服务器计算环境,启动时间比其他替代方案快100倍,称为Compute@Edge。
Shopify为全球100多万家不同的商家提供动力。而这些客户都有不同的需求。
为了保持代码库和用户体验的简单性,Shopify有一个产品原则:大部分时间构建大多数商家需要的东西。如果商家需要该核心集之外的功能,Shopify会提供一个带有第三方应用程序的应用程序商店来解决这一长尾需求。
其中许多应用程序都托管在自己的基础设施上,在闪电销售期间,活动有时会因为负载激增而被撤下。为了帮助应用程序开发者构建更稳定的应用程序,Shopify希望允许应用程序代码直接在Shopify内部运行。
但是,您如何才能快速安全地运行此第三方代码呢?通过使用WebAssembly。
有了建立在Lucet之上的新平台,他们已经能够在60秒的闪售窗口中运行12万个WebAssembly模块的闪售,同时将每个模块的运行时性能保持在10毫秒以下。
虽然Wasmtime是一个很好的通用WebAssembly运行时,但有时您需要为您的用例量身定做一些东西。许多开发人员正在其上构建更复杂的、专门构建的运行时。
Enarx是一个受信任的执行环境。它使您的数据完全保密,即使是对其运行的硬件也是如此。
WaSCC实现了一个参与者框架,用于连接消息代理和数据库等云本地服务。
一大重点是将治理模型正式化,这样我们就可以引入新成员。有一些很棒的潜在成员在生态系统中做着关键的工作,我们很愿意把他们带出来。要做到这一点,我们需要为如何举行选举和做出重要的技术决策等问题定义流程。我们需要把所有这些都写进规章制度,这样我们的合作伙伴才能知道他们签约的目的是什么。
今年的危机分散了我们对这项工作的注意力,但在适应新常态之后,我们取得了很好的进展。在这一点上,我们只是在做最后的润色。一旦这些都就位了,我们将能够接受新成员,并致力于扩大组织规模。
正如我们上面提到的,模块链接提案和接口类型提案都进展顺利。我们将专注于将这些建议提交给MVP,并在运行时和工具链中实现支持。我们预计这方面的大部分工作将在2021年上半年完成。
一旦接口类型的MVP就位,我们将能够开始与语言社区合作,将他们的语言类型映射到接口类型。这样,我们将能够最大限度地提高用不同语言编写的模块之间的互操作性,并在具有WASI支持的WebAssembly主机中轻松运行这些模块。