http://blog.csdn.net/zhangzq86/article/details/61195685

WebAssembly 的出现是不是意味着 Javascript 要完?

https://www.zhihu.com/question/34186498?sort=created

新时代

WebAssembly(简称Wasm)是一种新的适合于编译到Web的,可移植的,大小和加载时间高效的格式。这是一个新的与平台无关的二进制代码格式,目标是解决JavaScript性能问题。这个新的二进制格式远小于JavaScript,可由浏览器的JavaScript引擎直接加载和执行,这样可节省从JavaScript到字节码,从字节码到执行前的机器码所花费的即时编译JIT(Just-In-Time)时间。 作为一种低级语言,它定义了一个抽象语法树(Abstract Syntax Tree,AST),开发人员可以以文本格式进行调试。

WebAssembly描述了一个内存安全的沙箱执行环境,可以在现有的JavaScript虚拟机中实现。 当嵌入到Web中时,WebAssembly将强制执行浏览器的同源和权限安全策略。因此,和经常出现安全漏洞的Flash插件相比,WebAssembly是一个更加安全的解决方案。

WebAssembly可由C/C++等语言编译而来。此外,WebAssembly由Google、Mozilla、微软以及苹果公司牵头的W3C社区组共同努力,基本覆盖主流的浏览器厂商,因此其可移植性相较Silverlight等有极大提升,平台兼容问题将不复出现。

在Web平台的很多项目中,对于原生新功能的支持需要Web浏览器或Runtime提供复杂的标准化的API来实现,但是JavaScript API往往较慢。使用WebAssembly,这些标准API可以更简单,并且操作在更低的水平。例如,对于一个面部识别的Web项目,对于访问数据流我们可以由简单的JavaScript API实现,而把面部识别原生SDK做的事情交由WebAssembly实现。

需要了解的是,WebAssembly不是将C/C++等其他语言编译到JavaScript,更不是一种新的编程语言。

探究

asm.js

上文的c语言求和代码经由编译器生成asm.js后如代码3所示。

代码3

上述代码转换为WebAssembly的文本格式稍显复杂,为了理解方便,我们从精简的asm.js开始(见代码4)。

代码4

wast文本文件

将asm.js代码转换为WebAssembly的文本格式 add.wast(转换工具见本文工具链章节,如代码5所示)。

代码4

WebAssembly中代码的可装载和可执行单元被称为一个模块(module)。在运行时,一个模块可以被一组import值实例化,多个模块实例能够访问相同的共享状态。目前文本格式中的module主要用S表达式来表示。虽然S表达格式不是正式的文本格式,但它易于表示AST。WebAssembly也被设计为与ES6的modules集成。

一个单一的逻辑函数定义包含两个部分:功能部分声明在模块中每个内部函数定义的签名,代码段部分包含由功能部分声明的每个函数的函数体。WebAssembly是带有返回值的静态类型,并且所有参数都含有类型。上面的add.wast可以解读为:

  • 声明了一个名为$add的函数;
  • 包含两个参数a和b,两者都是32位整型;
  • 结果是一个32位整型;
  • 函数体是一个32位的加法:
  • 上面是局部变量$a得到的值;
  • 下面是局部变量$b得到的值;
  • 由于没有明确的返回节点,因此return是该加法函数的最后加载指令。

二进制Wasm文件

如图1所示,由C语言求和代码经过编译生成二进制文件,通读文件可以找到相应的头部、类型、导入、函数以及代码段等。通过JavaScript API载入Wasm二进制文件后,最终转换到机器码执行。

图1 经过编译的二进制文件

工具链

开发人员现在可以使用相应的工具链从C / C ++源文件编译WebAssembly模块。WebAssembly由许多工具支持,以帮助开发人员构建和处理源文件和生成的二进制内容。

Emscripten

Emscripten是其中无法回避的工具之一,如图2所示。在图2中,Emscripten SDK管理器(emsdk)用于管理多个SDK和工具,并且指定当前正被使用到编译代码的特定SDK和工具集。

图2 Emscripten工具链流程图及生成JavaScript(asm.js)流程

Emscripten的主要工具是Emscripten编译器前端(emcc),它是例如GCC的标准编译器的简易替代实现。

Emcc使用Clang将C/C++文件转换为LLVM(源自于底层虚拟机Low Level Virtual Machine)字节码,使用Fastcomp(Emscripten的编译器核心,一个LLVM后端)把字节码编译成JavaScript。输出的JavaScript可以由Node.js执行,或者嵌入HTML在浏览器中运行。这带来的直接结果就是,C和C++程序经过编译后可在JavaScript上运行,无需任何插件。

WABT和Binaryen

除此之外,对于想要使用由其他工具(如Emscripten)生成的WebAssembly二进制文件感兴趣的开发者,目前http://webassembly.org/官方额外提供了另外两组不同的工具:

  • WABT ——WebAssembly二进制工具包;
  • Binaryen——编译器和工具链。

WABT工具包支持将二进制WebAssembly格式转换为可读的文本格式。其中wasm2wast命令行工具可以将WebAssembly二进制文件转换为可读的S表达式文本文件。而wast2wasm命令行工具则执行完全相反的过程。

Binaryen则是一套更为全面的工具链,是用C++编写成用于WebAssembly的编译器和工具链基础结构库(如图3所示)。WebAssembly是二进制格式(Binary Format)并且和Emscripten集成,因此该工具以Binary和Emscript-en的末尾合并命名为Binaryen。它旨在使编译WebAssembly容易、快速、有效。它包含且不仅仅包含下面的几个工具。

图3 Binaryen生成WebAssembly流程

  • wasm-as:将WebAssembly由文本格式(当前为S表达式格式)编译成二进制格式;
  • wasm-dis:将二进制格式的WebAssembly反编译成文本格式;
  • asm2wasm:将asm.js编译到WebAssembly文本格式,使用Emscripten的asm优化器;
  • s2wasm:在LLVM中开发,由新WebAssembly后端产生的.s格式的编译器;
  • wasm.js:包含编译为JavaScript的Binaryen组件,包括解释器、asm2wasm、S表达式解析器等。

Binaryen目前提供了两个生成WebAssembly的流程,由于emscripten的asm.js生成已经非常稳定,并且asm2wasm是一个相当简单的过程,所以这种将C/C ++编译为WebAssembly的方法已经可用(如图4所示)。

图4 Emscripten+Binaryen生成WebAssembly的完整流程

由此可见,Emscripten以及Binaryen提供了完整的C/C++到WebAssembly的解决方案。而Binaryen则帮助提升了WebAssembly的工具链生态。

提示

由于WebAssembly正处于活跃开发阶段,各项编译步骤和编译工具会有大幅变更和改进,相信最终的编译工具和步骤会趋于便捷,开发者需要留意官方网站的最新动态。

实战

Linux和mac OS平台编译原生代码到WebAssembly可由如下步骤实现。

编译环境准备

操作系统必须有可以工作的编译器工具链,因此需要安装GCC、cmake环境,此外Python、node.js及Java环境也是需要的(其中Java为可选,如图5所示)。

图5 编译环境安装

如果是以其他方式安装了Node.js,可能需要更新~/.emscripten文件的NODE_JS属性。

安装正确的emscripten分支

要编译原生代码到WebAssembly,我们需要emscripten的incoming分支。由于emscripten不仅仅是用于WebAssembly的编译工具链,选择正确的分支尤为重要(如图6所示)。

图6 安装emscripten的incoming分支

其中URLTO具体的URL是https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz。

处理安装异常

可运行emcc -v命令进行验证安装。如果遇到如图7所示的错误,表明带有JavaScript后端的LLVM编译器并未被生成。

图7 emcc -v命令报错

图8 emcc -v命令报错解决方案

通过图8步骤,可以解决该问题,并且在~/.emscripten 文件中修改如下配置:

开始编译程序

现在一个完整的工具链已经具备,我们可以使用它来编译简单的程序到WebAssembly。但是,还有一些其他注意事项:

  • 必须通过参数-s Wasm=1到emcc(否则默认emcc将编译出asm.js);
  • 除了Wasm二进制文件和JavaScript wrapper外,如果还希望emscripten生成一个可直接运行的程序的HTML页面,则必须指定一个扩展名为.html的输出文件。

在编译之前,首先准备一个最基本的add.c程序,见代码6。

代码6

按代码7所示的命令编辑好add.c程序并编译:

运行WebAssembly应用

以Chrome浏览器为例,如果直接在浏览器内本地打开HTML文件,会有图9所示的错误: 

图9 XMLHttpRequest本地访问的跨域请求错误

由于XMLHttpRequest跨域请求不支持file://协议,必须经由HTTP实际输出,可以由python的SimplHTTPServer改进,见代码8:

代码8

在浏览器中输入http://127.0.0.1:8080并打开add.html,就能直接看到转换成WebAssembly的应用程序输出结果。

创建独立WebAssembly

默认情况下,emcc会创建JavaScript文件和WebAssembly的组合,其中JS加载包含编译代码的WebAssembly。对于C/C++开发人员,他们可能更倾向于创建独立的WebAssembly,用于JavaScript开发人员调用,见代码9。

代码9

上述命令运行后,我们可以得到独立的Wasm文件。需要说明的是,该参数仍然在开发中,可能随时发生规范和实现变更。

JavaScript API调用

从C/C++程序编译获得一个.wasm模块之后,JavaScript开发人员可以通过如下方式进行载入.wasm文件并执行。WebAssembly社区组也有计划通过Streams使用streaming以及异步编译,见代码10。

代码10

最后一行调用导出的WebAssembly函数,它反过来调用我们导入的JS函数,最终执行add(201700, 2),并且在控制台获得期望的结果输出(如图10所示)。

图10 WebAssembly求和函数在控制台的输出

性能

那么,WebAssembly的真实性能如何呢?首先我们用一直被用来作为CPU基准测试的斐波那契 (Fibonacci)数列来进行对比,这里使用的是性能较差的递归算法,在Node.js v7.2.1环境下,能够看到WebAssembly性能优势越发明显(如图11所示)。

图11 CPU基准测试反应WebAssembly的真实性能

再看看最基本的1000毫秒时间内,求和计算的运算量统计,在同一台计算机的Firefox 50.1.0版本的运算结果如图12所示。

图12 1000毫秒内求和计算的运算量统计

尽管重复测试时结果不尽相同,重启浏览器并多次测试取平均值后依然可以看到WebAssembly的运算量比JavaScript快了近一个量级。

Demo

图13展示了Angry Bots Demo,它是由WebAssembly项目发布的一个Demo,由Unity游戏移植而来。

图13 Angry Bots Demo / Google Chrome 55.0.2883.87

通过如下方式可以体验WebAssembly在浏览器中的强大性能。即便Google Chrome较新的稳定版也已支持WebAssembly,还是推荐使用canary版及Firefox的nightly版进行测试。

  1. 下载浏览器: 
    1-1. Google Chrome; 
    1-2. Mozilla Firefox; 
    1-3. Opera; 
    1-4. Vivaldi。
  2. 打开 WebAssembly支持 : 
    2-1. Google Chrome:chrome://flags/#enable-webassembly; 
    2-2. Mozilla Firefox:about:config→接受→搜索javascript.options.wasm→设置为true; 
    2-3. Opera:opera://flags/#enable-webassembly; 
    2-4. Vivaldi:vivaldi://flags#enable-webassembly。

访问:http://webassembly.org/demo/。

使用W、A、S、D等键实现移动操作,点击鼠标进行射击。该WebAssembly游戏在浏览器中运行相当流畅,媲美原生性能。

除了最新的浏览器开始对WebAssembly逐步支持外,Intel开源技术中心开发的Crosswalk项目(https://crosswalk-project.org/)早在2016年11月初的Crosswalk 22稳定版(Windows及Android 平台)即已加入对WebAssembly实验性的支持,开发者可以使用该版本体验Angry Bots Demo。

开发者

WebAssembly对于Web有显著的性能提升,对于开发者尤其是前端或者JavaScript开发人员而言,并不意味着WebAssembly将会取代JavaScript(如图14所示)。

图14 WebAssembly与JavaScript引擎的关系

WebAssembly被设计为对JavaScript的补充,而不是替代,是为了提供一种方法来获得应用程序的关键部分接近原生性能。随着时间的推移,虽然WebAssembly将允许多种语言(不仅仅是C/C++)被编译到Web,但是JavaScript的发展势头不会因此被削弱,并且仍然将保持Web的单一动态语言。此外,由于WebAssembly构建在JavaScript引擎的基础架构上,JavaScript和WebAssembly将在许多场景中配合使用。

那么WebAssembly是不是仅仅面向C/C++开发者呢?答案依旧是否定的。WebAssembly最初实现的重点是C/C++,由Mozilla主导开发的注重高效、安全和并行的Rust也能在2016年末被成功编译到WebAssembly了,未来还会继续增加其他语言的支持,见代码11。 

代码11

在未来,通过ES6模块接口与JavaScript集成,Web开发人员并不需要编写C++,而是可以直接利用其他人编写的库,重用模块化C++库可以像使用JavaScript中的modules一样简单。

进展

依据开发路线图,2016年10月31日,WebAssembly到达浏览器预览的里程碑。Google Chrome V8引擎及Mozilla Firefox SpiderMonkey引擎都已经在trunk上支持WebAssembly浏览器预览。2016年12月下旬,Microsoft Edge浏览器使用的JavaScript引擎ChakraCore v1.4.0启用了WebAssembly浏览器预览支持。而Webkit JavaScriptCore引擎对于该支持也在积极进行中。

目前,WebAssembly社区组已经有初始(MVP)二进制格式发布候选和JavaScript API在多个浏览器中实现。作为浏览器预览期间的一部分,WebAssembly社区组(WebAssembly Community Group)现在正在征求更广泛的社区反馈。社区组的初步目标是浏览器预览在2017年第一季度结束,但在浏览器预览期间的重大发现可能会延长该周期。当浏览器预览结束时,社区组将产生WebAssembly的草案规范,并且浏览器厂商可以开始默认提供符合规范的实现。预计在2017年上半年,四大主流浏览器对原生的WebAssembly支持将到达稳定版。

具体到Google V8引擎的最新进展,asm.js代码将不再通过Turbofan JavaScript编译器而是编译到WebAssembly后,在WebAssembly的原生执行环境中执行最终的机器码。这种改变带来的好处有,为asm.js将预先编译(AOT,Ahead Of Time Compilation)带到了Chrome,且完全向后兼容。新的WebAssembly编译渠道重用了一些Turbofan JavaScript编译器后端部分,因此能够在少了很多编译和优化消耗的前提下,产生类似的代码。在Google Chrome中,WebAssembly将很快在Canary版中默认启用,开发团队也期望能够发布到2017年第一季度末的稳定版中。

社区

包含所有主要浏览器厂商代表的W3C Web——Assembly社区组于2015年4月底成立。该小组的任务是,在编译到适用于Web的新的、便携的、大小和加载时间高效的格式上,促进早期的跨浏览器协作。该社区组也正在将WebAssembly设计为W3C开放标准。目前,除了文中所述主流浏览器厂商Mozilla、Google、微软、及苹果公司之外,Opera CTO及Intel的8位该领域专家均参与了该社区组。当然,并不是只有社区组成员才能参与标准的制定,任何人都可以在https://github.com/WebAssembly做出贡献。

展望

由于主要的浏览器厂商对WebAssembly支持表现积极,并且都在实现WebAssembly的各项功能,因此在Web中高性能需求的应用例如在线游戏、音乐、视频流、AR/VR、平台模拟、虚拟机、远程桌面、压缩及加密等都能够获得接近于原生的性能。相信WebAssembly将会开创Web的新时代。

转载于:https://www.cnblogs.com/bluestorm/p/7366280.html

WebAssembly 介绍相关推荐

  1. 基于webassembly的web报表设计器

    WebAssembly介绍 Webassembly(简称Wasm)是一种基于堆栈虚拟机的二进制指令格式.Webassembly用于编译C/C++/Rust等高级语言,生成一个可移植的目标,使客户端与服 ...

  2. webassembly学习

    webassembly webassembly学习 基本理论 webassembly介绍 wasm介绍 基本信息 为什么需要webassembly ASM.js(wasm的前身) wasm会替换jav ...

  3. WebAssembly 基础

    WebAssembly 介绍 官网介绍: WebAssembly 或者 wasm 是一个可移植.体积小.加载快并且兼容 Web 的全新格式.分析一下 WebAssembly 这个词由 Web 和 As ...

  4. WebAssembly 系列(一):生动形象地介绍 WebAssembly

    作者:Lin Clark  译者:@胡子大哈  英文原文:A cartoon intro to WebAssembly  译文地址:WebAssembly 系列(一)生动形象地介绍 WebAssemb ...

  5. webassembly类型_WebAssembly 那些事儿

    WebAssembly 那些事儿 什么是 WebAssembly? WebAssembly 是除 JavaScript 以外,另一种可以在网页中运行的编程语言,并且相比之下在某些功能和性能问题上更具优 ...

  6. qt webassembly 安装过程记录及注意事项

    一 安装emsdk 按照Download and install - Emscripten 3.1.6-git (dev) documentation 和Qt 官网介绍Qt for WebAssemb ...

  7. WebAssembly能不能取代JavaScript?15张卡通图给你答案!

    一切能用JavaScript实现的,终将用JavaScript实现. 一切能编译为WebAssembly的,终将编译为WebAssembly. 前端er们,WebAssembly用上了吗?在浏览器中快 ...

  8. Cloudflare Workers支持WebAssembly和键值存储

    Cloudflare最近宣布给他们的"无服务器"服务Workers新增两个附加功能:将WebAssembly作为JavaScript的替代方案,提供了对WebAssembly的支持 ...

  9. 前端每周清单半年盘点之 WebAssembly 篇

    前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点:分为新闻热点.开发教程.工程实践.深度阅读.开源项目.巅峰人生等栏目.欢迎关注[前端之巅]微信公众号(ID:front ...

  10. 百度嵌入式深度学习框架Paddle-Mobile介绍

    本篇内容介绍嵌入式深度学习的应用场景.Paddle-Mobile的特性优势以及使用开发方法,预计阅读时间4分钟 嵌入式深度学习有哪些应用 深度学习技术已经在互联网的诸多方向产生影响,关于深度学习和神经 ...

最新文章

  1. linux的变量用法
  2. 8636 跳格子(dfs+记忆化搜索)
  3. python raw input用法_如何在 python raw_input 中使用 tab 键补全?
  4. ORB-SLAM2运行时遇到的问题
  5. 小升初数学计算机考试题,重点中学小升初数学分班考试模拟试卷试题及解析总结计划-20210513100212.docx-原创力文档...
  6. 第五十一篇 仿真电路简单说明multisim12 电压表电流表
  7. 潜伏多年的中文编程语言该不该发展起来(科技无国界,呵呵)
  8. linux speedtest-cli工具测试网络带宽、测试网速(下载速度、上传速度和延迟等信息)
  9. 如何修改Bash Shell的提示符的格式和配色
  10. 蔡英珠:向前一步,跨越ICT“戈壁”
  11. Linux操作系统应用
  12. An attempt was made to call a method that does not exist. The attempt was ma
  13. mac mysql中文乱码问题(亲测有效)
  14. USB4Dock,USB4扩展坞方案 介绍
  15. MacW资讯:如何在Final Cut Pro X中安裝fcpx模板
  16. Nature 长文:打破AI黑盒的“持久战”
  17. 计算机在自动化未来领域方向,计算机在电力自动化系统中的应用实践(原稿)
  18. 2021-09-24 网安实验-音频隐写-Stegano之隐写1
  19. 没有对公账户怎么认证微信公众号?
  20. Android_Learning_Notes_Part 1

热门文章

  1. 初学FPGA一些建议
  2. linux内核系列之二_资源
  3. centos 网络开启
  4. 【原创】《算法导论》链表一章带星习题试解——附C语言实现
  5. ECMAScript 基础--原始值和引用值
  6. RAC安装时,报The specified nodes are not clusterable 的解决方法
  7. Load data local infile
  8. 要突破技术瓶颈?80%的人忽略了这个因素
  9. Rxjs初体验:制作语音测试工具
  10. .NetCore Session.Redis (转载)