WebAssembly是一种专为网络设计的编程语言,可生成浏览器可执行的二进制文件。而在2017年2月28日,四大浏览器一致宣布WebAssembly的MVP版本已经完成,即将推出浏览器可承载的稳定版本。WebAssembly的主要目标之一是速度快。本文将提供一些有关它如何变得更快的技术细节。当然,“快”是一个相对的概念。与JavaScript和其他动态语言相比,WebAssembly速度快主要是因为它的静态类型和方便的优化特性。WebAssembly的目标是在速度方面与本地执行一样快。事实上,asm.js已经比较接近这个目标,但WebAssembly还需要进一步缩短与本地执行速度的差距。所以这篇文章主要讨论为什么WebAssembly比asm.js更快。在开始介绍之前,先澄清一下:新技术总会有一些情况没有来得及优化,所以目前来说,并不是所有情况下WebAssembly都是最快的。这篇文章主要表达为什么WebAssembly应该更快。对于一些没那么快的情况,也是以后需要修复的问题。那么有了这些标准,让我们来介绍一下为什么WebAssembly更快。1.启动WebAssembly最初的设计目的是体积更小,下载速度更快,解析速度更快,这样即使应用于大型Web应用程序,也能快速启动。JavaScript代码是通过gzip压缩的,相比原生代码已经压缩了很多,想要进一步缩减它的体积确实不是一件容易的事。但通过对WebAssembly文件大小(LEB128指标)的精心设计,二进制格式的WebAssembly的文件大小在压缩后小于JavaScript。一般来说,它比gzip压缩后小10%-20%。WebAssembly在解析过程中有更大的改进:它的解析速度比JavaScript快一个数量级。这是因为WebAssembly的二进制格式被设计为更易于解析。同时,WebAssembly的解析和优化功能也更容易实现并行,在多核机器上体现得更好。除了下载和解析之外,影响启动时间的因素还有很多,比如VM对代码的全面优化,执行前必须下载额外的文件等等。但是下载和解析步骤无论如何都是不可避免的步骤,所以尽可能优化它们可能的。无论是对于浏览器还是应用程序,其他影响因素都有办法避免或减轻其影响(例如代码的全面优化,WebAssembly的基线编译器或解释器可以避免)。2.CPU特性使asm.js如此之快的技巧之一是利用CPU特性。JavaScript数字都是double类型,在asm.js中加法运算后会有一个按位AND运算,使得double加法运算在逻辑上与CPU进行simpleint加法(CPU执行simpleintaddition运算很快)是等价的.而asm.js巧妙地利用了这种方式,让VM可以更高效地使用CPU。但是有一些用JavaScript表达的东西是asm.js不能表达的。WebAssembly不受JavaScript的约束,让我们来看看更多可用的CPU特性:64位整数。基于64位整数的运算最多可以快4倍。例如,可以提高散列和加密算法的速度。内存读写偏移量。它的用途很广,基本上所有包含字段的内存对象都涉及到偏移量问题(比如C语言中的struct等)。未对齐的内存读写。这样就避免了asm.js需要的掩码(asm.js为了兼容TypedArray而做的操作),几乎所有的内存读写问题都可以使用。各种CPU指令,例如popcount、copysign等。每个指令在特定的使用场景中都有用(例如,popcount在密码分析中很有用)。它在每个特定场景中的用处取决于如何使用上述功能。与正常使用asm.js相比,我们的统计比asm.js快5%左右。未来可以利用更多CPU功能来提高速度,例如SIMD。3、工具链改进WebAssembly是编译器生成的主要目标,所以它的运行主要包括两部分:生成它的编译器(工具链端)和运行它的虚拟机(浏览器端)。良好的性能都取决于这两部分。对于asm.js,情况类似,Emscripten对toolchain做了一系列的优化,还有运行LLVM的优化器和Emscripten的asm.js优化器。WebAssembly的优化就是在这些基础上设计的,同时也加入了一些针对WebAssembly的改进。我们自己学习asm.js的过程帮助我们改进了WebAssembly,特别是在以下几个方面:我们使用BinaryenWebAssembly优化器而不是Emscriptenasm.js优化器,前者是为速度而设计的,其速度的改进在于更多优化步骤的成本。例如,在优化过程中将去除重复函数,这将使整体C++编译代码减少约5%。更好地优化冗余和复杂的控制流程,可以提高Relooper算法的效率,也有助于编译和解释类型循环。Binaryen优化器是通过实验设计和完善的,使用超级优化器进行实验将在各种情况下带来微妙的改进——我想asm.js也做了同样的事情。总体而言,这些工具链的改进在asm.js的基础上进一步提升了WebAssembly的速度(在Box2D速度评测中,WebAssembly的速度分别提升了5%和7%)。4.可预见的良好性能asm.js的速度非常接近原生执行的速度,但无法在所有浏览器中达到相同的标准。因为在使用asm.js的过程中,有的人尝试用一种方式优化asm.js,有的人则用另一种方式优化,这就导致不同的人版本不同,结果不同。虽然随着时间的推移,大家对asm.js已经形成了一定的共识,但是对于asm.js来说,本质的问题还是在于它还没有一个统一的标准。它只是一个供应商推出的JavaScript的非标准子集,其用户根据自己的喜好和习惯使用它。WebAssembly则不同,它是由几大浏览器厂商联合设计的。相对于JavaScript,JavaScript只能通过一些创新的方法或asm.js等方法来提高速度,这两种方法都不太可能适用于所有浏览器。WebAssembly的优化方案已经得到了大部分厂商的认可。对于WebAssembly,对于不同的VM(比如AOT和JIT有不同的编译方式)还有很大的提升空间。但基本可以断定的是,能够应用到全网的优秀性能是可以达到的。点击《WebAssembly 为什么比 asm.js 快?》阅读原文。【本文为专栏作者“虎子打哈”原创文章,转载请联系作者获得授权】点此阅读更多该作者好文
