这是有关WebAssembly的系列文章的第六部分,如果您还没有阅读其他文章,我们建议从头开始。
2017年2月28日,四大主流浏览器宣布他们一致认为WebAssembly的MVP已完成。这提供了一个稳定的初始版本,浏览器可以开始发行。
这提供了浏览器可以发布的稳定内核。该核心不包含社区组织计划的所有功能,但确实提供了足够的功能,可以使WebAssembly快速且可用。
这样,开发人员可以开始交付WebAssembly代码。对于早期版本的浏览器,开发人员可以发送一个asm.js版本的代码。因为asm.js是JavaScript的子集,所以任何JS引擎都可以运行它。使用Emscripten,您可以将同一应用程序编译为WebAssembly和asm.js。
即使在初始发行版中,WebAssembly也会很快。但是通过修复和新功能的组合,它将来应该会变得更快。
改善浏览器中的WebAssembly性能
随着浏览器改进其引擎中的WebAssembly支持,速度将有所提高。浏览器供应商正在独立处理这些问题。
JS和WebAssembly之间的更快的函数调用
当前,用JS代码调用WebAssembly函数的速度比需要的慢。那是因为它必须做一些叫做“踩踏”的事情。JIT不知道如何直接处理WebAssembly,因此必须将WebAssembly路由到可以处理的东西。这是引擎本身中的一小段代码,它确实进行了设置以运行优化的WebAssembly代码。
这可能比JIT知道如何直接处理它的速度慢100倍。
如果要将单个大型任务传递给WebAssembly模块,您将不会注意到此开销。但是,如果您在WebAssembly和JS之间有很多来回操作(就像处理较小的任务一样),那么这种开销是显而易见的。
加载时间更快
JIT必须在更快的加载时间和更快的执行时间之间进行权衡。如果您花费更多时间提前进行编译和优化,则可以加快执行速度,但会减慢启动速度。
有很多正在进行的工作来平衡前期编译(这确保一旦代码开始运行就不会产生麻烦),并且基本的事实是,大多数代码的运行时间不足以使优化值得进行。
由于WebAssembly无需推测将使用哪种类型,因此引擎不必担心在运行时监视类型。这给了他们更多的选择,例如使编译工作与执行并行化。
另外,JavaScript API的最新添加将允许WebAssembly的流式编译。这意味着当字节仍在下载时,引擎可以开始编译。
在Firefox中,我们正在使用两个编译器的系统。一个编译器将提前运行,并且在优化代码方面做得很好。在运行代码的同时,另一个编译器将在后台进行全面优化。完全优化的代码版本将在准备就绪时交换。
在规范中添加MVP后功能
WebAssembly的目标之一是指定小块并逐步进行测试,而不是预先设计所有内容。
这意味着可以预期有许多功能,但尚未100%完善。他们将必须执行规范过程,所有浏览器供应商都将参与其中。
这些功能称为未来功能。这里仅仅是少数。
直接使用DOM
当前,尚无法与DOM进行交互。这意味着您无法执行element.innerHTML
从WebAssembly更新节点的操作。
相反,您必须通过JS来设置值。这可能意味着将值传递回JavaScript调用者。另一方面,这可能意味着从WebAssembly中调用JavaScript函数-JavaScript和WebAssembly函数都可以用作WebAssembly模块中的导入。
无论哪种方式,通过JavaScript的速度都可能比直接访问的速度慢。WebAssembly的某些应用程序可能会一直存在,直到解决为止。
共享内存并发
加快代码速度的一种方法是使代码的不同部分可以同时并行运行。但是,这有时会适得其反,因为线程之间的通信开销可能比任务最初占用的时间更多。
但是,如果您可以在线程之间共享内存,则可以减少此开销。为此,WebAssembly将使用JavaScript的新SharedArrayBuffer。一旦在浏览器中安装了该组件,工作组就可以开始指定WebAssembly应该如何使用它们。
SIMD
如果您阅读其他文章或观看有关WebAssembly的讨论,则可能会听到有关SIMD支持的信息。首字母缩写词代表单条指令,多条数据。这是并行运行事物的另一种方式。
SIMD可以采用大数据结构,例如不同数字的向量,并同时将相同的指令应用于不同的部分。通过这种方式,它可以大大加快游戏或VR所需的各种复杂计算的速度。
对于一般的Web应用程序开发人员来说,这并不是太重要。但这对于使用多媒体的开发人员(例如游戏开发人员)非常重要。
异常处理
C ++等语言中的许多代码库都使用异常。但是,尚未将异常指定为WebAssembly的一部分。
如果使用Emscripten编译代码,它将模拟某些编译器优化级别的异常处理。但是,这非常慢,因此您可能需要使用该DISABLE_EXCEPTION_CATCHING
标志将其关闭。
一旦在WebAssembly中本地处理了异常,就不必进行此仿真。
其他改进-使开发人员更轻松
将来的某些功能不会影响性能,但会使开发人员更轻松地使用WebAssembly。
- 一流的源代码级开发人员工具。当前,在浏览器中调试WebAssembly就像调试原始程序集。但是,很少有开发人员能在思维上将其源代码映射到汇编。我们正在研究如何改善工具支持,以便开发人员可以调试其源代码。
- 垃圾收集。如果可以提前定义类型,则应该可以将代码转换为WebAssembly。因此,使用诸如TypeScript之类的代码应可编译为WebAssembly。但是,目前唯一的障碍是WebAssembly不知道如何与现有的垃圾收集器进行交互,例如JS引擎内置的垃圾收集器。此未来功能的想法是使WebAssembly通过一组低级GC基本类型和操作对内置GC进行一流访问。
- ES6 模块集成。浏览器当前添加了对使用
script
标记加载JavaScript模块的支持。添加此功能后,<script src=url type="module">
即使url指向WebAssembly模块,类似的标签也可以工作。
结论
WebAssembly如今发展很快,并且随着新功能和浏览器实现的改进,它应该会变得更快。
最后
介绍下本系列文章的源作者
Lin Clark
Lin在Mozilla的Advanced Development工作,主要研究Rust和WebAssembly。