WebAssembly,Web的新时代

本文深入探讨WebAssembly的起源、开发实践及其在Web性能提升中的作用。WebAssembly旨在解决JavaScript无类型导致的性能瓶颈,通过提供一种低级语言格式,允许C/C++等静态类型语言编译为高效的Web应用程序,提升执行速度。文章详细介绍了从asm.js到WebAssembly的演进过程,以及Emscripten和Binaryen等工具链在其中的作用。同时,通过实例展示了如何将C/C++代码编译为WebAssembly,并在浏览器中运行。随着各大浏览器厂商的支持,WebAssembly有望成为Web开发的重要组成部分,开启Web的新时代。
摘要由CSDN通过智能技术生成

作者:张敏,Intel开源技术中心Web团队软件技术经理,原Opera Software软件经理,在浏览器及Web Runtime领域工作10年,专注于Web及开源技术。
责编:陈秋歌(chenqg@csdn.net
本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅《程序员》

在浏览器之争中,Chrome凭借JavaScript的卓越性能取得了市场主导地位,然而由于JavaScript的无类型特性,导致其运行时消耗大量的性能做为代价,这也是JavaScript的瓶颈之一。WebAssembly旨在解决这一问题。本文从WebAssembly的起源到开发实践对其做全面探究,帮助开发者对WebAssembly有全面的了解。

缘起

让我们从浏览器大战说起。微软凭借Windows系统捆绑Internet Explorer的先天优势击溃Netscape后,进入了长达数年的静默期。而Netscape则于1998年将Communicator开源,并由Mozilla基金会衍生出Firefox浏览器,在2004年发布了1.0版本。从此,第二次浏览器大战拉开帷幕。这场大战由Firefox浏览器领衔,Safari、Opera等浏览器也积极进取,Internet Explorer的主导地位首次受到挑战。2008年Google推出Chrome浏览器,不但逐步侵蚀Firefox的市场,更是压制了老迈的Internet Explorer。在此次大战之后的2012年,StatCounter的数据指出Chrome以微弱优势超越Internet Explorer成为世界上最流行的浏览器。

分析Google Chrome浏览器战胜Internet Explorer的原因,除了对Web标准更友善的支持外,卓越的性能是其中相当重要的因素,而浏览器性能之争的本质则体现在JavaScript引擎。此前,JavaScript引擎的实现方式经历了遍历语法树到字节码解释器等较为原始的方式,将每条源代码翻译成相应的机器码并执行,并不保存翻译后的机器码,使得解释执行很慢。2008年9月,Google发布了V8 JavaScript引擎。V8被设计用于提高Web浏览器中JavaScript的执行性能,通过即时编译JIT(Just-In-Time)技术,在执行时将JavaScript代码编译成更为高效的机器代码并保存,下次执行同一代码段时无需再编译,使得JavaScript获得了几十倍的性能提升。

然而,JavaScript是个无类型(untyped,变量没有类型)的语言,这直接导致表达式c=a+b有多重含义:

  • a、b均为数字,则算术运算符+表示值相加;
  • a、b为字符串,则+运算符表示字符串连接;
  •  …

表达式执行时,JIT编译器需要检查a和b的类型,确定操作行为。若a、b均为数字,JIT编译器则将a、b确认为整型,而一旦某一变量变成字符串,JIT编译器则不得不将之前编译的机器码推倒重来。由此可见,JavaScript的无类型特性建立在消耗大量性能代价的基础之上。即便JIT编译器在对变量类型发生变化时已进行相应优化,但仍然有很多情况JavaScript引擎未进行或无法优化,例如for-of、try-catch、try-finally、with语句以及复合let、const赋值的函数等。

由此可见,JavaScript的无类型是JavaScript引擎的性能瓶颈之一,改进方案有两种:一是设计一门新的强类型语言并强制开发者进行类型指定;二是给现有的JavaScript加上变量类型。

微软开发的TypeScript属于第一种改进方案。它是扩展了JavaScript特性的语言,包含了类型批注,编译时类型检查,类型推断和擦除等功能,TypeScript开发者在声明变量时指定类型,使得JavaScript引擎能够更快将这种强类型的语言编译成弱类型。

看看第二种方案:

图片描述

代码1

代码1表示带有两个参数(a和b)的JavaScript函数,和通常JavaScript代码不同的地方在于a=a | 0及b=b | 0,以及返回值后面均利用标注进行了按位OR操作。这么做的优点是使JavaScript引擎强制转换变量的值为整型执行。通过标注加上变量类型,JavaScript引擎就能更快地编译。

既然增加变量类型能够提升Web性能,有没有办法将静态类型代码例如C/C++等转换成JavaScript指令的子集呢?上面的这段代码恰恰是作为JavaScript子集的asm.js,由代码2的C语言编译而来:

图片描述

代码2

事实上,早在1995年起就已经有Netscape Plugin API(NPAPI)在内的可以使用浏览器运行C/C++程序的项目在开发。而2013年问世的asm.js是目前较为广泛的方案。asm.js是一种中间编程语言,允许用C/C++语言编写的计算机软件作为Web应用程序运行,并保持更好的性能,而Mozilla Firefox从版本22起成为第一个为asm.js特别优化的网页浏览器。

Google也同样在为原生代码运行在Web端而努力。Google Native Client(NaCl)采用沙盒技术,让Intel x86、ARM或MIPS子集的机器码直接在沙盒上运行。它能够在无需安装插件的情况下从浏览器直接运行原生可执行代码,使Web应用程序可以用接近于机器码运作的速度来运行。而Google Portable Native Client(PNaCl)则稍有变化,通过一些前端编译器将C/C++源代码编译成LLVM的中间字节码而不是x86或ARM代码,并且进行优化以及链接&#x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值