原文:Where is WebAssembly now and what’s next?
本文译自Lin Clark 关于 WebAssembly 的卡通介绍系列,渣翻译,因此附上英文原文
- 概述:
- 背景:
- 现在的 WebAssembly:
- 未来的 WebAssembly:
- WebAssembly 的现状和未来?
On February 28, the four major browsers announced their consensus that the MVP of WebAssembly is complete. This provides a stable initial version that browsers can start shipping.
2月28日,四大浏览器宣布达成共识,WebAssembly 的最小可行的产品(MVP,Minimum Viable Product)已经完成。提供了一个稳定的初始版本,浏览器可以开始装备。
This provides a stable core that browsers can ship. This core doesn’t contain all of the features that the community group is planning, but it does provide enough to make WebAssembly fast and usable.
With this, developers can start shipping WebAssembly code. For earlier versions of browsers, developers can send down an
asm.js
version of the code. Becauseasm.js
is a subset of JavaScript, any JS engine can run it. WithEmscripten
, you can compile the same app to both WebAssembly andasm.js
.
Even in the initial release, WebAssembly will be fast. But it should get even faster in the future, through a combination of fixes and new features.
这提供了一个浏览器可以使用的稳定的核心。该核心不包含社区组织计划的所有功能,但它确实足以使 WebAssembly 快速并且可用。
这样,开发人员可以开始使用 WebAssembly 代码。使用浏览器提供的早期版本,开发人员可以发送给它 asm.js
版本的代码。因为 asm.js
是 JavaScript 的一个子集,任何 JS 引擎都可以运行。 使用 Emscripten
,你可以将同一的应用程序编译到 WebAssembly 和 asm.js
。
即使是初始版本,WebAssembly 也很快。并且通过修复和组合新功能,将来能够更快。
改善浏览器中的 WebAssembly 性能
Some speed improvements will come as browsers improve WebAssembly support in their engines. The browser vendors are working on these issues independently.
随着浏览器改进引擎中的 WebAssembly 支持,其速度将有所改善。各家浏览器厂商正在处理下面这些问题。
JS 和 WebAssembly 之间更快的函数调用
Currently, calling a WebAssembly function in JS code is slower than it needs to be. That’s because it has to do something called “trampolining”. The
JIT
doesn’t know how to deal directly with WebAssembly, so it has to route the WebAssembly to something that does. This is a slow piece of code in the engine itself, which does setup to run the optimized WebAssembly code.
目前,在 JS 代码中调用 WebAssembly 函数比它需要的要慢。 那是因为它必须做一些叫做“蹦床”的东西。 JIT
不知道如何直接处理 WebAssembly,所以它必须将 WebAssembly 路由到某个地方处理。这是引擎本身中缓慢的一段代码,它会设置运行优化的 WebAssembly 代码。
This can be up to 100x slower than it would be if the
JIT
knew how to handle it directly.
You won’t notice this overhead if you’re passing a single large task off to the WebAssembly module. But if you have lots of back-and-forth between WebAssembly and JS (as you do with smaller tasks), then this overhead is noticeable.
这种方式可能比 JIT
知道如何直接处理的速度要慢 100 倍。
如果你将单个大型任务传递到 WebAssembly 模块,则不会注意到此开销。 但是如果你在 WebAssembly 和 JS 之间有很多相互交互(就像使用较小的任务一样),那么这个开销是显而易见的。
更快的加载时间
JIT
s have to manage the tradeoff between faster load times and faster execution times. If you spend more time compiling and optimizing ahead of time, that speeds up execution, but it slows down start up.
There’s a lot of ongoing work to balance up-front compilation (which ensures there is no jank once the code starts running) and the basic fact that most parts of the code won’t be run enough times to make optimization worth it.
JIT
必须管理更快的加载时间和更快的执行时间之间的权衡。如果你提前花费更多时间进行编译和优化,则可以加快执行速度,但启动速度会减慢。
有很多正在进行的工作来平衡前端编译(确保代码开始运行后不会有任何崩溃),而事实上,大部分代码不会运行足够多的时间使其优化值得被进行。
Since WebAssembly doesn’t need to speculate what types will be used, the engines don’t have to worry about monitoring the types at runtime. This gives them more options, for example parallelizing compilation work with execution.
Plus, recent additions to the JavaScript API will allow streaming compilation of WebAssembly. This means that the engine can start compiling while bytes are still being downloaded.
In Firefox we’re working on a two-compiler system. One compiler will run ahead of time and do a pretty good job at optimizing the code. While that’s running code, another compiler will do a full optimization in the background. The fully-optimized version of the code will be swapped in when it’s ready.
由于 WebAssembly 不需要推测将要使用什么类型,引擎不必担心在运行时监视类型。这给了它们更多的选择,例如并行编译工作与执行。
此外,最新添加的 JavaScript API 将允许 WebAssembly 的流式编译。这意味着引擎可以在字节仍在下载时就开始编译。
在 Firefox 中,我们正在开发一个双编译器系统。一个编译器将提前运行,并在优化代码方面做得很好。当运行代码时,另一个编译器将在后台进行完全优化。完全优化的代码版本将在准备就绪时被交换。
Adding post-MVP features to the spec
One of the goals of WebAssembly is to specify in small chunks and test along the way, rather than designing everything up front.
This means there are lots of features that are expected, but haven’t been 100% thought-through yet. They will have to go through the specification process, which all of the browser vendors are active in.
These features are called future features. Here are just a few.
一个 WebAssembly 的目标是在小部分中设计和测试,一路发展,而不是预先设计所有内容。
这意味着有许多预期的功能还没有 100%
的想法,它们需要经过所有浏览器供应商积极制定的规范流程。
这些就是未来的功能,这里仅仅列出少数。
直接与DOM工作
Currently, there’s no way to interact with the DOM. This means you can’t do something like
element.innerHTML
to update a node from WebAssembly.
Instead, you have to go through JS to set the value. This can mean passing a value back to the JavaScript caller. On the other hand, it can mean calling a JavaScript function from within WebAssembly—both JavaScript and WebAssembly functions can be used as imports in a WebAssembly module.
目前,没有办法与 DOM 进行交互。这意味着你不能像 element.innerHTML
那样从 WebAssembly 更新节点。
相反,你必须通过 JS 去设置值。这可能意味着将值传回给 JavaScript 调用者。 另一方面,它也可以意味着从 WebAssembly 中调用 JavaScript 函数 —— JavaScript 和 WebAssembly 函数都可以在 WebAssembly 模块中用作导入。
Either way, it is likely that going through JavaScript is slower than direct access would be. Some applications of WebAssembly may be held up until this is resolved.
无论哪种方式,通过 JavaScript 可能会比直接访问 DOM 慢。一些 WebAssembly 的应用程序可能会被阻止,直到被解决。
共享内存并发
One way to speed up code is to make it possible for different parts of the code to run at the same time, in parallel. This can sometimes backfire, though, since the overhead of communication between threads can take up more time than the task would have in the first place.
But if you can share memory between threads, it reduces this overhead. To do this, WebAssembly will use JavaScript’s new
SharedArrayBuffer
. Once that is in place in the browsers, the working group can start specifying how WebAssembly should work with them.
加快代码的一种方法是使代码的不同部分同时运行成为可能,也就是并行。这有时可能会起反作用,因为线程之间的通信开销可能比任务单独执行占用更多的时间。
但是,如果你可以在线程之间共享内存,可以减少这种开销。 为此,WebAssembly 将使用 JavaScript 的新 SharedArrayBuffer
功能。 一旦 SharedArrayBuffer
在浏览器中可用,工作组就可以开始指定 WebAssembly 如何与它们配合使用。
SIMD
If you read other posts or watch talks about WebAssembly, you may hear about
SIMD
support. The acronym stands for single instruction, multiple data. It’s another way of running things in parallel.
SIMD
makes it possible to take a large data structure, like a vector of different numbers, and apply the same instruction to different parts at the same time. In this way, it can drastically speed up the kinds of complex computations you need for games or VR.
This is not too important for the average web app developer. But it is very important to developers working with multimedia, such as game developers.
如果你阅读其它 WebAssembly 帖子或观看介绍,你可能会听到有关 SIMD
的支持。SIMD
缩写代表单指令,多数据。 这是并行运行的另一种方式。
SIMD
使得可以采用大量的数据结构,例如不同数字的向量,同时将相同的指令应用于不同的部分。这样,它可以大大加快游戏或 VR
所需的各种复杂的计算。
对于一般的网络应用开发人员来说,这并不重要。但对于开发多媒体的开发人员,比如游戏开发者来说,这是非常重要的。
异常处理
Many code bases in languages like
C++
use exceptions. However, exceptions aren’t yet specified as part of WebAssembly.
If you are compiling your code with
Emscripten
, it will emulate exception handling for some compiler optimization levels. This is pretty slow, though, so you may want to use theDISABLE_EXCEPTION_CATCHING
flag to turn it off.
Once exceptions are handled natively in WebAssembly, this emulation won’t be necessary.
许多语言的代码库如 C++
使用了异常。 但是,异常还没有被指定为 WebAssembly 的一部分。
如果你正在使用 Emscripten
编译代码,它将模拟某些编译器优化级别的异常处理。 这很慢,但是你可能希望使用 DISABLE_EXCEPTION_CATCHING
标志来关闭它。
一旦在 WebAssembly 中原生的处理了异常,则不需要这种仿真。
其它改进 - 使开发人员更容易
Some future features don’t affect performance, but will make it easier for developers to work with WebAssembly.
- First-class source-level developer tools. Currently, debugging WebAssembly in the browser is like debugging raw assembly. Very few developers can mentally map their source code to assembly, though. We’re looking at how we can improve tooling support so that developers can debug their source code.
- Garbage collection. If you can define your types ahead of time, you should be able to turn your code into WebAssembly. So code using something like
TypeScript
should be compilable to WebAssembly. The only hitch currently, though, is that WebAssembly doesn’t know how to interact with existing garbage collectors, like the one built in to the JS engine. The idea of this future feature is to give WebAssembly first-class access to the builtin GC with a set of low-level GC primitive types and operations.- ES6 Module integration. Browsers are currently adding support for loading JavaScript modules using the script tag. Once this feature is added, a tag like
<script src=url type="module">
could work even if url points to a WebAssembly module.
一些未来的功能不会影响性能,但会使开发人员更轻松地使用 WebAssembly。
- 一流的源代码开发工具。 目前,在浏览器中调试 WebAssembly 就像调试原始汇编。 正因为如此,只有很少有开发人员可以将它们的源代码在头脑中映射到汇编。 我们正在研究如何改进工具支持,以便开发人员可以调试其源代码。
- 垃圾回收。 如果您可以提前定义类型,您应该可以将代码转换为 WebAssembly。 所以使用像
TypeScript
这样的代码应该可以编译为 WebAssembly。 目前唯一的阻碍是 WebAssembly 不知道如何与现有的垃圾收集器(如内置在 JS 引擎的垃圾回收器)进行交互。 未来,这个功能的想法是使 WebAssembly 能够使用一组底层的 GC 原语类型和操作对内置 GC 进行访问。 - ES6模块集成。 浏览器正在添加使用脚本标签加载 JavaScript 模块的支持。 添加此功能后,即使 url 指向 WebAssembly 模块,标签如
<script src = url type =“module”>
也可以工作。
总结
WebAssembly is fast today, and with new features and improvements to the implementation in browsers, it should get even faster.
今天的 WebAssembly 很快,并且随着浏览器新功能的实现和改进,会更快。