认识 WebAssembly

自从Brendan Eich用十天时间创造了JavaScript,人们对它的吐槽就从未间断过。众所周知JavaScript是一门动态语言。运行于JavaScript引擎中,我们熟悉的有Mozilla的SpiderMonkey,Safari的JavaScriptCore,Edge的Chakra还有大名鼎鼎的V8。V8引擎将JavaScript的运行效率提升到一个新的level。所以后来的Nodejs也采用V8作为引擎,实现了用js进行后端开发的愿景。

然而JavaScript发展到今天,其语言基因中存在的缺陷并不能得到根本性的改变。比如常见的加法操作

function add(a, b) {
    return a + b;
}

这段代码在浏览器中的运行过程比你想象的复杂。
add在被调用前,js引擎并不能提前预判传入参数的类型,需要在运行时对参数进行如下一连串的类型判断和转换操作。

pic

对js加法运算的详细操作(keng)有兴趣的可以看这篇文章

V8再快也难以逾越语言本身的瓶颈。这种问题是动态语言的弊端,对于此类问题,业界已经出现了非常多的解决方案。

而本文要讲的正是目前最为前沿的一种 ------ WebAssembly

WebAssembly这个概念其实2015年就提出来了,而就在不久之前,四大浏览器厂商,Chrome, Firefox, Edge, Safari 在新版的浏览器中才全部默认支持Webassembly(Chrome, Firefox早于后两者),这种技术很快将在前端高性能开发领域中大放异彩。

WebAssembly是什么?

下面是来自官方的定义:

WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

关键词:”format",WebAssembly 是一种编码格式,适合编译到web上运行。

事实上,WebAssembly可以看做是对JavaScript的加强,弥补JavaScript在执行效率上的缺陷。

  • 它是一个新的语言,它定义了一种AST,并可以用字节码的格式表示。

  • 它是对浏览器的加强,浏览器能够直接理解WebAssembly并将其转化为机器码。

  • 它是一种目标语言,任何其他语言都可以编译成WebAssembly在浏览器上运行。

想象一下,在计算机视觉,游戏动画,视频编解码,数据加密等需要需要高计算量的领域,如果想在浏览器上实现,并跨浏览器支持,唯一能做的就是用JavaScript来运行,这是一件吃力不讨好的事情。而WebAssembly可以将现有的用C,C++编写的库直接编译成WebAssembly运行到浏览器上, 并且可以作为库被JavaScript引用。那就意味着我们可以将很多后端的工作转移到前端,减轻服务器的压力。这是WebAssembly最为吸引人的特性。并且WebAssembly是运行于沙箱中,保证了其安全性。

为什么要有WebAssembly?

如果只是想让C,C++,Java等原生语言编写的模块运行在浏览器上。我们只需要一个转换器,将源语言转换为目标语言JavaScript,而这种技术其实很早就有了。

例如将Java转换成JavaScript的Google Web Toolkit (GWT)

将python转换成JavaScript的pyjamas 等等。

但是这并没有解决JavaScript执行慢的问题,这跟直接用JavaScript来重写代码库是一样的作用。这就是为什么Electron能直接运行Node.js但对比传统桌面应用依然弱鸡的原因。

要理解JavaScript为什么运行慢,就要理解它在引擎中的处理过程。
传统JavaScript在V8引擎中的编译过程是这样的:首先JavaScript会被编译成AST,然后引擎再将AST, 转化为机器语言交给底层执行。

V8的pipeline结构会进一步先将AST转化为一种中间代码,再对中间代码再次生成优化后的机器码,从而实现更快的执行速度。

pic

对于WebAssembly来说,前面的parser, optimize 全部省了,直接编译到机器码。

pic

浏览器通过增加一种语言格式的编译支持,来实现执行效率的突破。

WebAssembly除了运行快之外,其特殊的二进制表示法也大大减小了代码包的大小。同时提升了浏览器的加载速度。

如何使用WebAssembly?

现在你已经能在这些浏览器中使用WebAssembly了。

WebAssembly这么快,但并不意味着JavaScript这门语言要从此绝迹了。

如前面所说,WebAssembly和JavaScript之间是可以相互调用的。

假设我们用C写了这段代码

include 
int add(int a, int b) {
    return a + b;
}

首先将其转化为wasm文件, 这里运用一个线上的工具 WasmFiddle

将转化的add.wasm下载下来。

由于目前还没支持

你可能感兴趣的:(webassembly,asm.js,v8)