WebAssembly 的现状及其未来?

这是关于 WebAssembly 及其速度优势的系列文章的第六部分。如果您还没有阅读过其他文章,我们建议您从 开头 开始。

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 代码。

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

这可能比 JIT 直接处理它要慢 100 倍。

如果您将单个大型任务传递给 WebAssembly 模块,您不会注意到这种开销。但是,如果您在 WebAssembly 和 JS 之间有大量的来回传递(就像您在处理较小的任务时所做的那样),那么这种开销是显而易见的。

更快的加载时间

JIT 必须管理更快加载时间和更快执行时间之间的权衡。如果您花更多时间提前编译和优化,这会加快执行速度,但会减慢启动速度。

正在进行大量工作来平衡提前编译(这确保了代码一旦开始运行就不会出现卡顿)和基本事实,即大多数代码部分不会运行足够多的次数来使优化值得。

由于 WebAssembly 不需要推测将使用哪些类型,因此引擎不必担心在运行时监控类型。这给了它们更多选择,例如将编译工作与执行并行化。

此外,对 JavaScript API 的最新添加将允许 WebAssembly 的流式编译。这意味着引擎可以在下载字节时开始编译。

在 Firefox 中,我们正在开发一个双编译器系统。一个编译器将提前运行并对代码进行相当好的优化。在运行代码的同时,另一个编译器将在后台执行完全优化。完全优化的代码版本将在准备好时被替换。

向规范添加 MVP 后功能

WebAssembly 的目标之一是按小块进行规范并在过程中进行测试,而不是预先设计所有内容。

这意味着有很多功能是预期的,但还没有被完全考虑。它们必须经过规范流程,所有浏览器供应商都积极参与其中。

这些功能被称为未来功能。这里只列举几个。

直接与 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 支持的内容。这个缩写代表单指令多数据。它是并行运行事物的一种方法。

SIMD 使得能够获取一个大型数据结构(如不同数字的向量),并同时将相同的指令应用于不同的部分。这样,它可以极大地加速游戏或 VR 所需的复杂计算类型。

这对普通 Web 应用程序开发者来说并不太重要。但对于使用多媒体(如游戏开发者)的开发者来说,它非常重要。

异常处理

许多像 C++ 这样的语言中的代码库使用异常。但是,异常还没有被指定为 WebAssembly 的一部分。

如果您使用 Emscripten 编译代码,它将为某些编译器优化级别模拟异常处理。不过,这很慢,所以您可能希望使用 <a href="https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html#c-exceptions">DISABLE_EXCEPTION_CATCHING</a> 标志将其关闭。

一旦异常在 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 的高级开发部门工作,专注于 Rust 和 WebAssembly。

更多 Lin Clark 的文章……


20 条评论

  1. Marius Schulz

    对 WebAssembly 的精彩介绍。感谢您撰写了这个系列,Lin!:)

    2017 年 2 月 28 日 下午 10:13

    1. Lin Clark

      很高兴它对您有所帮助!

      2017 年 2 月 28 日 下午 1:59

  2. Art Scott

    你好,Lin。

    曾经,我们在设计空间中所关心的只是 s/t 空间和时间

    现在设计空间是 E/s/t 能量/空间/时间感知的

    我期待着 WA E/s/t 故事
    希望 WA 社区能够发展并讲述 WA E 的故事。

    Mahalo,感谢 Art

    2017 年 2 月 28 日 下午 10:35

  3. 匿名

    WebAssembly 能否为 DRM 保护机制提供更高的安全性和弹性?

    2017 年 2 月 28 日 下午 7:23

  4. Felix Almeida

    感谢您撰写了这些文章。干得好!

    2017 年 2 月 28 日 下午 9:48

  5. Wink Saville

    感谢您,非常有信息量!

    2017 年 2 月 28 日 下午 10:43

  6. Hunan Rostomyan

    感谢您提供的信息丰富且美观的系列文章。

    2017 年 2 月 28 日 下午 11:36

  7. AB

    WASM 不可能成为“JSVM”吗?这将为您提供一个选择,要么为 WASM 编译 JS,要么让它被 JIT 解释。

    我相信 C# 4 和 Lisp 有许多动态特性,但它们也是编译语言。

    2017 年 3 月 1 日 上午 3:53

  8. Felix Bernhardt

    很棒的系列,我迫不及待地想开始使用 WebAssembly!所有这些新可能性真的令人兴奋。

    非常感谢!

    2017 年 3 月 1 日 下午 4:48

  9. Phuong Nguyen

    感谢您分享这个令人惊叹的消息,Lin :),我迫不及待地想要在当前的 Web 应用程序中使用它,直到它更稳定为止。您是否有一个 WebAssembly API 或规范的 URL,以便我可以提前熟悉它?

    2017 年 3 月 2 日 上午 7:09

    1. Lin Clark

      很高兴它对您有所帮助!

      您可以在 WebAssembly 网站 上了解更多有关规范和 API 的信息。我们还在 Mozilla 开发者网络 上提供了更多文档。

      2017 年 3 月 2 日 上午 7:13

  10. Marzio

    Lin,感谢你写了关于 WebAssembly 的系列文章。你让它看起来非常简单直观。

    2017 年 3 月 3 日 上午 4:46

  11. Chris

    感谢这个系列,非常有信息量!

    关于 WebAssembly 本身,我很高兴主要浏览器在这方面达成一致。asm.js 是一个非常棒且有创意的想法,但它终究只是个权宜之计。

    WebAssembly 是我们很多人期盼的干净解决方案,它只会越来越好(即更快更易用)。

    2017 年 3 月 4 日 上午 3:40

  12. Mehdi

    刚刚读完这个系列,写得很好。谢谢!

    2017 年 3 月 6 日 上午 4:50

  13. Agrim Prasad

    一个很棒的系列,对 WebAssembly 给出了相当详细且直观的介绍。期待着很快尝试它。

    非常感谢 Lin!

    2017 年 3 月 6 日 下午 7:38

  14. Anh Hoang

    嗨!

    我开始学习 React、Flux、Redux、Graphql 时就知道你的代码卡通了。现在,我打算学习 WebAssembly、Rust,然后我又遇到了你的代码卡通。这是命运吗 :))。

    非常感谢 Lin!你拯救了我的职业生涯!

    2017 年 3 月 8 日 上午 8:59

  15. Tomer

    我通常不会评论我读过的文章,但这一篇真的很棒,非常感谢。

    2017 年 3 月 10 日 上午 7:31

  16. Vladimir Z.

    哇,刚刚读完这个很棒的系列!
    它非常有趣且清晰,我喜欢这些卡通。

    学到了很多东西,谢谢。

    2017 年 3 月 10 日 下午 12:02

  17. Kyle Hale

    谢谢!作为一个非 Web 开发人员,我能够很好地理解,这都要归功于你非常清晰的解释!干得好!

    2017 年 3 月 28 日 上午 9:12

  18. Andreas B. H. Nielsen

    WebAssembly 是我的学士学位项目的核心内容,这些文章非常有帮助。谢谢!

    2017 年 3 月 29 日 上午 5:36

本文评论已关闭。