WebAssembly初印象

JavaScript在网页编程中一直具有统治性的地位,在网页进化的历程中,JavaScript的性能提升经历了不断地改革。
它原本的执行速度并不算快,其中一次转折比较大的点在2008年,许多浏览器引入 Just-in-time (JIT,文章后面还会提到)编译器,大大提高了JavaScript的执行效率,这也让JavaScript开始能在后端领域被使用。

随着网页内容的丰富,在网页中实现3D游戏、音视频处理得到了越来越多的关注,但在网页中如何提供更好的速度和体验感一直是一个挑战。
JavaScript作为一种弱类型语言,前端的逻辑在不断的壮大,需要更多的限制来更好的帮助程序员之间的协作。
所以就出现了一些想要解决的问题:

  1. 语法过于灵活。
  2. 性能。

语法过于灵活

针对于这一点,市面上出现了TypeScript,为JS加入静态类型检查。
但这样最后还是要编译成JS,对性能没有提升。

曾经の解决方法

  • 谷歌研制出了Dart,给浏览器引入新的虚拟机去直接运行Dart程序以提升性能,但只限于谷歌浏览器,用的人不多。
  • 火狐推出了asm.js,它是JS的子集,让引擎针对asm.js做性能优化。asm.js的语法太简单,限制多。

什么是WebAssembly

WebAssembly是一种新的字节码格式
和JS需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似,可快速装载运行,因此性能相对于 JS 解释执行大大提升。
用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行, 浏览器厂商需要做的就是根据 WebAssembly 规范实现虚拟机。
由于非常接近机器码,可以非常快的被翻译为对应架构的机器码。

WebAssemblyの优点

  • 体积小。
    浏览器只加载编译好的字节码,一样的逻辑比用JS体积要小很多。

  • 加载快。
    体积小,无需解释执行。

  • 兼容性问题少。
    WebAssembly制订好后很少变动。可能出现兼容性问题的地方在于JS和WebAssembly桥接的接口规范。

为什么它比JavaScript更快?

首先,JavaScript运行消耗的时间有以下几个任务:

  1. Parsing:源代码→解释器可运行的代码所花的时间;
  2. Compiling+optimizing:基线编译器和优化编译器花的时间(P.S:一些优化编译器不在主线程运行,所以不包括)
  3. Re-optimizing: JIT发现优化假设错误,丢弃优化代码所花的时间。包括重优化的时间、抛弃并返回到基线编译器的时间。
  4. Execution:执行代码的时间
  5. Garbage collection:垃圾回收,清理内存的时间
    这些任务是交叉执行的,比如正在进行解析过程时,其他一些代码正在运行,而另一些正在编译。

这几个阶段不是按顺序来的,有部分代码可能在1阶段,有的可能在3阶段,等等。这样的规律也正是JIT带来的,也是因为这样,JS的效率才得到了提升。
WebAssembly本身就算是中间代码,不需要像JS代码一样被分解为抽象语法树后再进行转换。在代码开始被编译优化之前,也不需要知道它的类型。
并且JIT对不同的编译器做了不同的优化处理,这也是为什么一段代码,可能在谷歌浏览器运行很快,但是在其他浏览器中没这么快,而WebAssembly在这时候已经经历过优化的过程,可以省略掉这段优化的时间。在垃圾回收上,WebAssembly主要是让开发者们自己写代码去手动回收,浏览器在默认情况下都是自动进行回收,这样有时候其实没有这个检查的必要。

能编译为WebAssembly的高级语言

目前能编译成WebAssembly的高级语言有:

  • AssemblyScript
    语法和TypeScript一致。
  • c\c++
    官方推荐的方式。
  • Rust
    语法复杂。
  • Kotlin
    语法和Java、JS相似。
  • Golang:
    语法简单。对WebAssembly还处于未正式发布阶段。

WebAssemblyの展望

综上,WebAssembly非常适用于需要大量计算的场景:

  • 在浏览器中处理音视频。
  • dom diff用WebAssembly重写能提升性能。RN的应用性能也能提升。
  • 大型3D网页游戏(白鹭引擎已经开始探索用WebAssembly)。

结语

这篇总结是我整合了网上的一些文章和资料而写成的,仅供学习和参考,谢谢。