本文是图说 WebAssembly 系列文章的最后一篇。若是您还未阅读以前的文章,建议您从第一篇入手。html
2017 年 2 月 28 日,主流的四大浏览器达成了共识并宣布 WebAssembly 的最小可行产品(MVP)已经完成。这是 WebAssembly 搭载在浏览器上的第一个稳定初始版本。git
这也为浏览器提供了一个稳定的 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 代码的准备过程。数据结构
这个种处理方式可能比直接由 JIT 处理慢 100 倍。并发
若是将一个大型任务交给 WebAssembly 模块来完成的话,咱们可能不会注意到这种开销。
可是若是咱们在 WebAssembly 和 JavaScript 之间来回屡次调用,那么这个问题就凸显出来了。dom
JIT 必须在更快的加载时间和更快的运行之间作出权衡。
若是花费更多的时间在编译和优化,虽然能够提高运行速度,可是也下降了启动性能。函数
一个基本事实是,大多数的代码的运行次数其实都还达不到须要优化的地步。
不过,目前有许多正在进行的研究,在寻找预编译和这样的基本事实之间的平衡点。
因为 WebAssembly 并不须要推测数据类型,因此引擎也不须要在运行时监视这些数据类型的变化。
这也就给了咱们更多的选择余地,例如把编译和运行并行化。
此外,最近新增的 JavaScript API 容许对 WebAssembly 进行流式编译。也就是说,引擎能够在 .wasm 还没下载完成的时候就开始对已下载的内容进行编译。
在 Firefox,咱们正在开发双编译系统。一个编译器会提早运行,并把代码优化工做作得至关不错。等到运行代码的时候,另外一个编译器会在后台进行全优化工做。一旦代码优化完成,便会当即替换掉旧代码。
WebAssembly 的设计目标之一是先支持小部分功能并同步进行测试,而不是从一开始就把方方面面都设计好。
所以,它还有更多功能值得期待,不过新功能还没进行周全的考虑。只有全部浏览器厂商都积极参与才能把新功能写进规范。
如下是一些新功能。
目前,WebAssembly 没有任何方式可以操做 DOM 。因此咱们不能像使用 element.innerHTML
同样,从 WebAssembly 里更新一个 DOM 节点。
相反,必须经过 JavaScript 才能改变 DOM 节点。
也就是说,必须把新值返回给 JavaScript 调用方。或者在 WebAssembly 中调用 JavaScript 函数。这是能够实现的,由于 JavaScript 和 WebAssembly 函数均可以作为 WebAssembly 模块的导入。
无论使用哪一种方式,绕道 JavaScript 确定比直接操做 DOM 要慢。这就致使了部分 WebAssembly 应用可能会所以而推迟发布时间。
有一种提升运行速度的办法是,使不一样代码同时并行运行。
不过这有时候可能会偷鸡不成蚀把米,由于线程间通讯可能比任务自己耗费的时间还多。
可是若是可以在不一样线程之间共享内存,那么这种状况就会好不少。为此,WebAssembly 可使用 JavaScript 的新接口 SharedArrayBuffer
来实现内存共享。一旦浏览器开始支持 SharedArrayBuffer
,WebAssembly 工做小组就立马能够开始为之制定相关标准。
SIMD(Single Instruction, Multiple Data)是“单指令多数据”的缩写。它是实现并行化的另外一种方式。
SIMD 能够接受一个大型数据结构(好比一个包含不一样数值的向量),而后对其中的不一样数据同时应用相同的指令。这种方式能够大幅提高游戏或者 VR 中的各类复杂计算。
这对普通的网页应用开发者可能没那么重要。可是对于像游戏等多媒体应用开发者就显得尤其重要了。
不少语言都支持异常处理,可是 WebAssembly 还没有有相关异常处理的规范。
若是你使用 Emscripten 编译代码,你会发现它会模拟某些编译器优化级别的异常处理。
不过这会致使编译变慢,可是你能够经过 DISABLE_EXCEPTION_CATCHING
标志来关闭它。
若是 WebAssembly 自己就可以处理异常,那么这种异常模拟就不必了。
也有一些将来的功能并不会影响性能,可是却能提高 WebAssembly 的开发体验。
script
来加载模块的功能。等到该功能完成后,把 <script src=url type="module">
这种标签指向 WebAssembly 模块也应该是可以支持的。现现在 WebAssembly 已经至关快速。随着新功能和改进逐步实现,相信它必定能够变得更快!