图说 WebAssembly(六):现状与展望

本文是图说 WebAssembly 系列文章的最后一篇。若是您还未阅读以前的文章,建议您从第一篇入手。html

现状

2017 年 2 月 28 日,主流的四大浏览器达成了共识并宣布 WebAssembly 的最小可行产品(MVP)已经完成。这是 WebAssembly 搭载在浏览器上的第一个稳定初始版本。git

logo_party01-500x169.png

这也为浏览器提供了一个稳定的 WebAssembly 核心。虽然该核心还很差汉社区组正在计划的全部功能,但它也确实提供了足够的功能,使得 WebAssembly 快速且可用。github

从这一刻开始,开发者也能够开始发布 WebAssembly 代码了。对于较早版本的浏览器,开发者能够回退到使用 asm.js 版本的代码。由于 asm.js 是 JavaScript 的子集,因此任何 JavaScript 引擎均可以运行它。
若是使用 Emscripten 的话,还能够把相同的应用编译为 WebAssembly 版本和 asm.js 版本的代码。web

即便是最初的发行版本,WebAssembly 也是高性能的。可是随着问题的修复和新功能的添加,它在将来将会拥有更高性能。segmentfault

提升性能

随着浏览器逐步改进对 WebAssembly 的支持,性能提高也会慢慢的显现。目前,浏览器厂商们正在独自改进下面这些问题。浏览器

更快的函数调用

当前,在 JavaScript 中调用 WebAssembly 函数比想象的要慢。这是由于这个过程必须经历一个称为弹跳(Trampolining)的过程。JIT 并不知道如何直接处理 WebAssembly,因此它必须把 WebAssembly 转移到知道如何处理它的地方去。这在引擎内部是一个很慢的过程,该过程会创建用来运行 WebAssembly 代码的准备过程。数据结构

06-02-trampoline01.png

这个种处理方式可能比直接由 JIT 处理慢 100 倍。并发

若是将一个大型任务交给 WebAssembly 模块来完成的话,咱们可能不会注意到这种开销。
可是若是咱们在 WebAssembly 和 JavaScript 之间来回屡次调用,那么这个问题就凸显出来了。dom

更快的加载

JIT 必须在更快的加载时间和更快的运行之间作出权衡。
若是花费更多的时间在编译和优化,虽然能够提高运行速度,可是也下降了启动性能。函数

一个基本事实是,大多数的代码的运行次数其实都还达不到须要优化的地步。
不过,目前有许多正在进行的研究,在寻找预编译和这样的基本事实之间的平衡点。

因为 WebAssembly 并不须要推测数据类型,因此引擎也不须要在运行时监视这些数据类型的变化。
这也就给了咱们更多的选择余地,例如把编译和运行并行化。

此外,最近新增的 JavaScript API 容许对 WebAssembly 进行流式编译。也就是说,引擎能够在 .wasm 还没下载完成的时候就开始对已下载的内容进行编译。

在 Firefox,咱们正在开发双编译系统。一个编译器会提早运行,并把代码优化工做作得至关不错。等到运行代码的时候,另外一个编译器会在后台进行全优化工做。一旦代码优化完成,便会当即替换掉旧代码。

新增功能

WebAssembly 的设计目标之一是先支持小部分功能并同步进行测试,而不是从一开始就把方方面面都设计好。

所以,它还有更多功能值得期待,不过新功能还没进行周全的考虑。只有全部浏览器厂商都积极参与才能把新功能写进规范。

如下是一些新功能。

直接操做 DOM

目前,WebAssembly 没有任何方式可以操做 DOM 。因此咱们不能像使用 element.innerHTML 同样,从 WebAssembly 里更新一个 DOM 节点。

相反,必须经过 JavaScript 才能改变 DOM 节点。
也就是说,必须把新值返回给 JavaScript 调用方。或者在 WebAssembly 中调用 JavaScript 函数。这是能够实现的,由于 JavaScript 和 WebAssembly 函数均可以作为 WebAssembly 模块的导入。

06-03-dom01-768x642.png

无论使用哪一种方式,绕道 JavaScript 确定比直接操做 DOM 要慢。这就致使了部分 WebAssembly 应用可能会所以而推迟发布时间。

共享内存并发

有一种提升运行速度的办法是,使不一样代码同时并行运行。
不过这有时候可能会偷鸡不成蚀把米,由于线程间通讯可能比任务自己耗费的时间还多。

可是若是可以在不一样线程之间共享内存,那么这种状况就会好不少。为此,WebAssembly 可使用 JavaScript 的新接口 SharedArrayBuffer 来实现内存共享。一旦浏览器开始支持 SharedArrayBuffer,WebAssembly 工做小组就立马能够开始为之制定相关标准。

SIMD

SIMD(Single Instruction, Multiple Data)是“单指令多数据”的缩写。它是实现并行化的另外一种方式。

SIMD 能够接受一个大型数据结构(好比一个包含不一样数值的向量),而后对其中的不一样数据同时应用相同的指令。这种方式能够大幅提高游戏或者 VR 中的各类复杂计算。

这对普通的网页应用开发者可能没那么重要。可是对于像游戏等多媒体应用开发者就显得尤其重要了。

异常处理

不少语言都支持异常处理,可是 WebAssembly 还没有有相关异常处理的规范。

若是你使用 Emscripten 编译代码,你会发现它会模拟某些编译器优化级别的异常处理。
不过这会致使编译变慢,可是你能够经过 DISABLE_EXCEPTION_CATCHING 标志来关闭它。

若是 WebAssembly 自己就可以处理异常,那么这种异常模拟就不必了。

提高开发体验的改进

也有一些将来的功能并不会影响性能,可是却能提高 WebAssembly 的开发体验。

  • 一等的源码开发工具。目前,在浏览器中调试 WebAssembly 就像直接调试汇编。虽然仍是可以调试,可是基本上不多开发者可以把它跟源码关联起来。因此,咱们正在研究该如何改进工具支持,从而实现能够直接调试源码。
  • 垃圾回收。若是可以事先定义数据的类型,那么就可以把这类代码变成 WebAssembly 。因此使用 TypeScript 这类语言编写的代码,是能够跟 WebAssembly 兼容的。不过,目前惟一的困难是 WebAssembly 还不知道该如何与现有的垃圾回收机制结合,就像 JavaScript 引擎内置的垃圾回收同样。
  • ES6 模块集成。浏览器目前正在完善使用 script 来加载模块的功能。等到该功能完成后,把 <script src=url type="module"> 这种标签指向 WebAssembly 模块也应该是可以支持的。

结束

现现在 WebAssembly 已经至关快速。随着新功能和改进逐步实现,相信它必定能够变得更快!

相关文章
相关标签/搜索