WebAssembly资料

本文不含原创,只是知识的搬运工。

1 WebAssembly起源

1.1. What is WebAssembly?

来源:https://webassembly.org/
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

来源:https://zhuanlan.zhihu.com/p/68048524
WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式。

当然,我知道,即使你看了定义也不知道WebAssembly到底是什么东西。废话不多说,我们通过一个简单的例子来看看WebAssembly到底是什么。

WebAssembly例子

上图的左侧是用C++实现的求递归的函数,中间是十六进制的Binary Code,右侧是指令文本。而中间的十六进制的Binary Code就是WebAssembly。

大家可以看到,其可写性和可读性差到无法想象。那是因为WebAssembly不是用来给各位用手一行一行撸的代码,WebAssembly是一个编译目标。什么是编译目标?当我们写TypeScript的时候,Webpack最后打包生成的JavaScript文件就是编译目标。可能大家已经猜到了,上图的Binary就是左侧的C++代码经过编译器编译之后的结果。

1.2. 由来

来源:https://zhuanlan.zhihu.com/p/68048524

1.2.1. 性能瓶颈

在业务需求越来越复杂的现在,前端的开发逻辑越来越复杂,相应的代码量随之变的越来越多。相应的,整个项目的起步的时间越来越长。在性能不好的电脑上,启动一个前端的项目甚至要花上十多秒。这些其实还好,说明前端越来越受到重视,越来越多的人开始进行前端的开发。

但是除了逻辑复杂、代码量大,还有另一个原因是JavaScript这门语言本身的缺陷,JavaScript没有静态变量类型。这门解释型编程语言的作者Brendan Eich,仓促的创造了这门被广泛使用的语言,以至于JavaScript的发展史甚至在某种层面上变成了填坑史。为什么说没有静态类型会降低效率,这会涉及到一些JavaScript引擎的知识。

1.2.2. 静态变量类型所带来的问题

ChakraCore引擎结构

这是Microsoft Edge浏览器的JavaScript引擎ChakraCore的结构。我们来看一看我们的JavaScript代码在引擎中会经历什么。

  • JavaScript文件会被下载下来。
  • 然后进入Parser,Parser会把代码转化成AST(抽象语法树)。
  • 然后根据抽象语法树,Bytecode Compiler字节码编译器会生成引擎能够直接阅读、执行的字节码。
  • 字节码进入翻译器,将字节码一行一行的翻译成效率十分高的Machine Code.

在项目运行的过程中,引擎会对执行次数较多的function记性优化,引擎将其代码编译成Machine Code后打包送到顶部的Just-In-Time(JIT) Compiler,下次再执行这个function,就会直接执行编译好的Machine Code。但是由于JavaScript的动态变量,上一秒可能是Array,下一秒就变成了Object。那么上一次引擎所做的优化,就失去了作用,此时又要再一次进行优化。

1.2.3. asm.js出现

所以为了解决这个问题,WebAssembly的前身,asm.js诞生了。asm.js是一个JavaScript的严格子集,合理合法的asm.js代码一定是合理合法的JavaScript代码,但是反之就不成立。同WebAssembly一样,asm.js不是用来给各位用手一行一行撸的代码,asm.js是一个编译目标。它的可读性、可写性虽然比WebAssembly好,但是对于开发者来说,仍然是无法接受的。

asm.js强制静态类型,举个例子。

1
2
3
4
5
6
function asmJs() {
'use asm';

let myInt = 0 | 0;
let myDouble = +1.1;
}

为什么asm.js会有静态类型呢?因为像0 | 0这样的,代表这是一个Int的数据,而+1.1则代表这是一个Double的数据。

1.2.4. asm.js不能解决所有的问题

可能有人有疑问,这问题不是解决了吗?那为什么会有WebAssembly?WebAssembly又解决了什么问题?大家可以再看一下上面的ChakraCore的引擎结构。即便asm.js对静态类型的问题做的再好,它始终逃不过要经过Parser,要经过ByteCode Compiler,而这两步是JavaScript代码在引擎执行过程当中消耗时间最多的两步。而WebAssembly不用经过这两步。这就是WebAssembly比asm.js更快的原因。

1.2.5. WebAssembly横空出世

所以在2015年,我们迎来了WebAssembly。WebAssembly是经过编译器编译之后的代码,体积小、起步快。在语法上完全脱离JavaScript,同时具有沙盒化的执行环境。WebAssembly同样的强制静态类型,是C/C++/Rust的编译目标

2. WebAssembly的优势

来源:https://zhuanlan.zhihu.com/p/68048524

2.1. WebAssembly和asm.js性能对比

下面的图是Unity WebGL使用和不使用WebAssembly的起步时间对比的一个BenchMark,给大家当作一个参考。

Measured on Windows

可以看到,在FireFox中,WebAssembly和asm.js的性能差异达到了2倍,在Chrome中达到了3倍,在Edge中甚至达到了6倍。通过这些对比也可以从侧面看出,目前所有的主流浏览器都已经支持WebAssembly V1(Node >= 8.0.0)。

2.2. 与JavaScript做对比

我自己在一个用create-react-app新建的项目中,分别对比了WebAssembly版本和原生JavaScript版本的递归无优化的Fibonacci函数,下图是这两个函数在值是45、48、50的时候的性能对比。

Fibonacci函数性能对比:WebAssembly vs JavaScript

看图说话,这就是WebAssembly与JavaScript很实际的一个性能对比,几乎稳定地是JavaScript的两倍。

3. WebAssembly在大型项目中的应用

来源:https://zhuanlan.zhihu.com/p/68048524

在这里能够举的例子还是很多,比如AutoCAD、GoogleEarth、Unity、Unreal、PSPDKit、WebPack等等。拿其中几个来简单说一下。

3.1. AutoCAD

这是一个用于画图的软件,在很长的一段时间是没有Web的版本的,原因有两个,其一,是Web的性能的确不能满足他们的需求。其二,在WebAssembly没有面世之前,AutoCAD是用C++实现的,要将其搬到Web上,就意味着要重写他们所有的代码,这代价十分的巨大。

而在WebAssembly面世之后,AutoCAD得以利用编译器,将其沉淀了30多年的代码直接编译成WebAssembly,同时性能基于之前的普通Web应用得到了很大的提升。正是这些原因,得以让AutoCAD将其应用从Desktop搬到Web中。

3.2. Google Earth

Google Earth也就是谷歌地球,因为需要展示很多3D的图像,对性能要求十分高,所以采取了一些Native的技术。最初的时候就连Google Chrome浏览器都不支持Web的版本,需要单独下载Google Earth的Destop应用。而在WebAssembly之后呢,谷歌地球推出了Web的版本。而据说下一个可以运行谷歌地球的浏览器是FireFox。

3.3. Unity和Unreal游戏引擎

这里给两个油管的链接自己体验一下,大家注意科学上网。

4. WebAssembly要取代JavaScript?

4.1. WebAssembly要取代JavaScript?

答案是否定的,请看下图。

WebAssembly与JavaScript的协作关系

大家可以看到这是一个协作关系。WebAssembly是被设计成JavaScript的一个完善、补充,而不是一个替代品。WebAssembly将很多编程语言带到了Web中,但是JavaScript因其不可思议的能力,仍然将保留现有的地位。

在我的个人理解上,WebAssembly并没有要替代JavaScript,一统天下的意思。我总结下来就两个点:

  • 给了Web更好的性能
  • 给了Web更多的可能

关于WebAssembly的性能问题,之前也花了很大的篇幅讲过了。而更多的可能,随着WebAssembly的技术越来越成熟,势必会有更多的应用从Desktop被搬到Web上,这会使本来已经十分强大的Web更加丰富和强大。

4.2. 什么时候使用WebAssembly?

说了这么多,我到底什么时候该使用它呢?总结下来,大部分情况分两个点:

  • 性能有很高要求的App/Module/游戏
  • Web中使用C/C++/Rust/Go的库

举个简单的例子。如果你要实现的是Web版本的Ins或者Facebook,你想要提高效率,那么就可以把其中对图片进行压缩、解压缩、处理的工具,用C++实现,然后再编译回WebAssembly。

5. WebAssembly的几个开发工具

  • AssemblyScript。支持直接将TypeScript编译成WebAssembly。这对于很多前端同学来说,入门的门槛还是很低的。
  • Emscripten。可以说是WebAssembly的灵魂工具不为过,上面说了很多编译,这个就是那个编译器。将其他的高级语言编译成WebAssembly
  • WABT。是个将WebAssembly在字节码和文本格式相互转换的一个工具,方便开发者去理解这个wasm到底是在做什么事。

6. Language Support

(截止至2022-07-13)来源:https://webassembly.org/getting-started/developers-guide/

Language Support

其它语言(C#,F#,Kotlin,Pascal,Zig,Grain)的介绍可以在上面的链接中找到。

其它来源的总结:https://www.fermyon.com/wasm-languages/webassembly-language-support

总结了top 20 languages能够在被编译成Wasm后,运行在browser、非browser环境和WASI环境:
Language Support 2

7. Roadmap

来源:https://webassembly.org/roadmap/

In November 2017, WebAssembly CG members representing four browsers, Chrome, Edge, Firefox, and WebKit, reached consensus that the design of the initial (MVP) WebAssembly API and binary format is complete to the extent that no further design work is possible without implementation experience and significant usage.

MVP = Minimum Viable Product
来源1:https://en.wikipedia.org/wiki/Minimum_viable_product

A minimum viable product (MVP) is a version of a product with just enough features to be usable by early customers who can then provide feedback for future product development.

来源2:https://www.zhihu.com/question/37254490/answer/71546119
MVP(minimum viable product,最小化可行产品)概念最早由埃里克·莱斯提出,刊载于哈弗商业评论,并有出版物《精益创业》。

和常规产品不同,MVP更侧重于对未知市场的勘测,用最小的代价来验证你的商业可行性。举个例子,如果你希望做一个图片分享网站,那么作为产品原型,MVP仅仅包含最基础的功能,形态或许就是一个提交图片的按钮以及图片的展示。借助MVP,经过一系列实践,产品的设计思路将被一次次整改,最终完成正式版的开发。

MVP的目的——更快地接触客户
按照常规的开发方式,从调研、到设计、到开发再到推向市场,会是一个漫长的过程,而且很难有人会保证成功率。但当换一种方式,以MVP进行小样调研,快速进入市场、接触客户并得到反馈,透过反馈不断修改原型,并进行不断的迭代开发,极大减少了试错成本。

After the initial release, WebAssembly has been gaining new features through the standardization process. For the complete list of current proposals and their respective stages, check out the WebAssembly/proposals repo.

The table below aims to track implemented features in popular engines:
Implemented Features in Popular Engines

全文摘自

[1] WebAssembly官网:https://webassembly.org/
[2] WebAssembly完全入门——了解wasm的前世今身:https://zhuanlan.zhihu.com/p/68048524
[3] WebAssembly Language Support Matric:https://www.fermyon.com/wasm-languages/webassembly-language-support
[4] Minimum viable product:https://en.wikipedia.org/wiki/Minimum_viable_product
[5] 什么是营销中的「最小化可行产品」(MVP)?:https://www.zhihu.com/question/37254490/answer/71546119