【译】WebAssembly 的现状与未来 —— WebAssembly 系列(六)

译者:Mactavish (博主本人)

链接:http://www.zcfy.cc/article/4163

原文:https://hacks.mozilla.org/2017/02/where-is-webassembly-now-and-whats-next

这是 “WebAssembly 以及为什么它这么快” 这个系列的第六部分。如果你还没阅读其他的部分,我们建议你 从头开始阅读

在 2 月 28 日, 四大主要浏览器一致宣布 WebAssembly 的 MVP(最低可行性产品)已经完成。 这标志着WebAssembly 的稳定初始版本可供浏览器开始发行。

这意味着浏览器可以发行稳定的核心部分。这个核心部分并没有包含的社区组织计划中的所有特性,但是它能确保 WebAssembly 迅速而有效。

如此,开发者们可以开始输送 WebAssembly 代码。对于更早版本的浏览器,开发者们可以向下输出一个 asm.js 版本的代码。因为 asm.js 是 JavaScript 的一个子集,任意一个 JS 引擎都能够运行它。有了 Emscripten,你可以将同一个应用编译成 WebAssembly 和 asm.js。

甚至在最开始的发布版本中,WebAssembly 的运行速度都很快。但是通过一些系列的修补和新特性,它未来应该会变得更快。

提高 WebAssembly 在浏览器中的性能

随着浏览器引擎对WebAssembly 的支持度的提升,WebAssembly 的运行速度也会得到一定的提升。浏览器厂商都在独立地解决这些问题。

JS 与 WebAssembly 之间的快速函数调用

目前,在 JS 代码里调用一个 WebAssembly 函数比它预期的要慢。 那是因为它必须要执行一些叫做“蹦床”(trampolining)的东西。JIT 并不知道要怎么直接处理 WebAssembly,所以它只能将 WebAssembly 输送到够处理它的地方。这是引擎本身的一小块代码,用来设置并运行优化过的 WebAssembly 代码。

Person jumping from JS on to a trampoline setup function to get to WebAssembly

这个过程可能比 JIT 知道如何直接处理它要慢 100 多倍。

如果你只是将单个大型的任务传输到 WebAssembly 模块中处理,你是不会注意到它开销的。但是,如果你需要在 WebAssembly 和 JS 之间来回的处理一些简单的任务,那么这种开销就能很容易被注意到。

更快的载入时间

JIT 需要在快速载入和快速执行之间权衡。如果你花费了很多时间用于提前编译和优化代码,它的确会提升执行速度,但是就降低了启动速度。

仍需要很多工作去平衡早期的编译(以确保代码开始运行的时候没有任何糟糕的东西),而且事实上,大部分代码并不值得优化,因为它们运行的时候不够长。

由于 WebAssembly 不需要推测它要使用的类型,那么引擎就不需要担心在运行时需要监测它。这就给了它们更多的选择,比如并行编译和执行。

此外,最近新增的 JavaScript API 允许 WebAssembly 流编译。这意味着引擎可以在数据包(字节)仍在下载的时候就开始编译。

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.

在火狐浏览器中,我们致力于实现一个双编译的系统。一个编译器会提前优化好代码。虽然那是运行中的代码,另外一个编译器会在后台做全面地优化。当全面优化过后的代码准备好的时候,他就会被切换进去执行。

增加后 MVP 特性到规格中

WebAssembly 的其中目标之一就是指定在小范围内测试,而不是提前就设计好所有的东西。

这意味着还有很多特性值得期待,但是它们都还没有 100% 讨论通过。这些特性必须经过规范流程,这样所有的浏览器厂商才能将其实现。

这些特性叫做未来特性。这里有一些未来特性。

直接和 DOM 交互

目前,我们还没有办法直接和 DOM 进行交互。这意味着我们没办法使用像 element.innerHTML 这样的方法来直接使用 WebAssembly 更新一个节点。

相反,你必须使用 JS 来设置值。这意味着要将值传递回 JavaScript 来调用。 另一方面,这意味着可以从 WebAssembly 内部调用 JavaScript 函数 —— JavaScript 和 WebAssembly 函数都导入到 WebAssembly 模块当中使用。

Person reaching around from WebAssembly through JS to get to the DOM

无论哪种方式,都可能比直接使用 JavaScript 要慢。一些 WebAssembly 的实际应用可能还要等到这个问题解决。

共享内存并发

提高代码运行速度的方式之一就是代码的不同部分同时并行运行。这有时候会适得其反,因为线程之间的通信花费的时间往往比任务原本执行的时间要更长。

但是,如果你可以在线程之间共享内存,就可以减少开销。为了达到这个目的,WebAssembly 会使用 JavaScript 的新特性 —— SharedArrayBuffer。一旦这个特性在浏览器中实现了之后,工作组就可以开始指定 WebAssembly 要如何和它们协作。

单指令多数据技术(SIMD)

如果你读过其谈论 WebAssembly 的文章,你或许听说过 SIMD 支持。这个缩写代表单指令多数据(single instruction, multiple data)。它是并行的另外一种实现。

SIMD 可以使用大型的数据结构,像不同数字的向量,来对不同的部分在同一时间执行相同的指令。这样,它就能彻底地加速游戏和 VR 所需的复杂计算的速度。

这对于一般的 web app 开发者来说没那么重要。但是对于和多媒体打交道的开发者,比如游戏开发者来说,是非常重要的。

异常处理

许多编程语言的代码库,比如 C++ 使用了异常。然而异常还没有明确规定为 WebAssembly 的一部分。

如果你正在用 Emscripten 编译代码,它会模仿在一些编译器优化级别的异常处理。虽然这个非常慢,因此你或许想使用[DISABLE_EXCEPTION_CATCHING](https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html#c-exceptions) 标识来关掉这个功能。

一旦异常可以通过原生的 WebAssembly 处理,这些模拟就没有必要了。

其他改进 —— 对开发者更友好

一些未来特性虽然不会影响性能,但是它使得开发者能够更好的使用 WebAssembly。

  • 一流的源码级别的开发者工具。 目前在浏览器中 debug WebAssembly 就像是在 debug 原生的汇编一样。 很少能有开发者能够在脑子将他们源码映射到汇编。我们正在完善工具支持,这样开发者就能 debug 他们的源码。

  • 垃圾回收。 如果你能够提前定义类型,那么你就能够将你的代码转换成 WebAssembly。所以像使用TypeScript 的代码就能够被编译成 WebAssembly。目前唯一的障碍是尽管 WebAssembly 并不知道如何与现有的垃圾回收器交互,比如 JS 引擎内内置的垃圾回收器。这个未来特性的概念就是给 WebAssembly 一些低级的 GC 原始类型和操作来一流地访问内置 GC。

  • ES6 模块集成。浏览器目前正在添加对使用 script 标签来加载 JavaScript 模块的支持。一旦这个特性被加入到浏览器中,像 <script src=url type="module"> 这样的标签就能够起作用,哪怕 url 指向的是一个 WebAssembly 模块。

总结

WebAssembly 目前已经很快了,随着浏览器实现新的特性以及功能的改进,它应该会变得更快。

关于

Lin Clark

Lin 是 Mozilla Developer Relations 团队的一名工程师。 She 专注于 JavaScript, WebAssembly, Rust, 以及 Servo,同时也绘制一些关于编码的漫画。

Lin Clark 的更多文章

转载于:https://my.oschina.net/JSBreaker/blog/1536932

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值