近年来,随着浏览器朝着第二操作系统的目标突飞猛进,我们可以发现越来越多的桌面应用被移植到了web端,点击链接即打开应用的操作模式收到广泛追捧,浏览器端实现各种高性能应用势在必行。
然而很多优秀的高性能应用,比如3D图形渲染、游戏引擎、视音频编解码等底层大都是基于C/C++实现的。如果要用web主流脚本语言JavaScript将其重构一遍,必定“道阻且长”。那么,如果我们能将C/C++直接编译成JavaScript呢,是不是就能将应用无缝运行在浏览器上?
实际上这个大开的脑洞来源于大名鼎鼎的Mozilla,除了Filefox浏览器,javascript、HTML5、Rust等互联网发展的重要基石都是这家公司的产物。基于将C/C++编译成javascript的想法,Mozilla成立了编译器Emscripten开发项目。
官网对于Emscripten的描述为
由此可见
①Emscripten可以将C/C++编译成javascript(WebAssembly,不是普通的javascript)
②除了C/C++,Emscripten可转换任何LLVM支持的语言,如Go、Rust、Toy
1、WebAssembly——浏览器与C**/C++的桥梁**
官网中提到C/C++经Emscripten的编译后的产物是WebAssembly,没错,正是WebAssembly搭建起了浏览器与C语言的桥梁。WebAssembly并不是一开始就有的,Emscripten最早期的编译结果是asm.js,WebAssembly是由Asm.js衍生出的更底层的语言技术。
要了解asm.js和WebAssembly,首先我们来看一下javascript在浏览器引擎中是怎么工作的。
Javascript是一种弱类型语言,在编译过程中存在较大的优化空间。比如V8引擎的即时编译(Just-in-Time Compilation,JIT),其中最成功的技术之一是类型特化(Type specialization),用来推导Javascript的动态变量类型。又比如垃圾回收优化算法,用来加快垃圾回收速度,减少其对应用程序的影响。
Mozilla的工程师在开发Emscripten的过程中也注意到了这点,并提出了一种特殊的javascript——asm.js。asm.js是一种强类型语言,并且去掉了大部分的自动垃圾回收机制,能够更大程度的优化编译过程,因此获得了比原生javascript更快的运行速度。
asm.js 是一个 Javascript 的严格子集,本质上还是Javascript,脱离不了Parsing和Generating Bytecode。那如果我们绕过js,直接将C/C++编译成更底层的语言,是否能进一步提升运行效率呢?答案是肯定的,2015年WebAssembly横空出世。WebAssembly 是现代浏览器可以运行的低字节代码,于2017年推出早期版本,2019年正式加入web标准,成为现代浏览器第四大开发语言。
WebAssembly的优势主要有:
①更小:紧凑的二进制格式比gzip压缩后的JavaScript代码体积小约10%~20%;
②更快:得益于更接近底层的二进制格式,WebAssembly执行速度接近原生代码,且能在多核CPU上并行解析;
③跨平台:与平台无关的代码格式,支持在不同的 Web 浏览器和操作系统上运行;
④安全性:在沙箱环境中运行,保护系统免受恶意代码侵害;
⑤灵活性:支持C/C++、Rust等多种编程语言,可与javascript无缝协作,在开发社区中得到了广泛支持。
目前大多数的浏览器厂商都已支持WebAssembly,包括Edge。在浏览器控制台页面输入WebAssembly,我们可以看到打印出的WebAssembly对象。
WebAssembly提供了一系列js函数接口,使得js可以丝滑调用WebAssembly模块。C/C++代码也是基于js调用得以在浏览器上运行。
Step1: C/C++、Rust、Go等语言编译wasm(WebAssembly)模块。
Step2: JavaScript加载wasm模块
Step3: JavaScript调用wasm模块函数,即C/C++编写的高性能应用功能
安装Emscripten对C/C++源码进行编译,会生成以下三个文件:
l hello.wasm:编译成的二进制 wasm模块代码
l hello.js:用来转换原生C函数和 JavaScript/wasm的胶水代码
l hello.html:用来实例化wasm 代码并将它输出在浏览器上显示的html文件
这时我们可以用node写一个简单的服务器,然后在浏览器上访问本地服务(WebAssembly需要http服务器发布访问),浏览器控制台中就能看到“Hello World”的输出了!是不是很神奇?
2、大有可为的WebAssembly和不可取代的javascript
WebAssembly在web端已经取得了一些应用,如:
①Google Earth。谷歌地球3D绘制对性能要求非常高,起初只能在自家谷歌浏览器中运行。改用WebAssembly技术后,可以在Firefox、Edge、Opera浏览器中运行。
②FFmpeg-音视频处理。是 WebAssembly在web端应用非常广的技术,哔哩哔哩网站中就用到了FFmpeg来加速视频编解码。
③Photoshop Web版。对于photoshop这样复杂的应用,WebAssembyl实现了web端和pc端由同一份源码生成,并由此解决性能问题。目前photoshop已发布了在线测试版本。
其他很多出色的应用。Unity\ Unreal游戏引擎、Microsoft Office、AutoCAD、Figma设计工具、Zoom在线会议等等。
WebAssembly不是仅限于前端的技术,其在浏览器内运行,靠的是javascript胶水代码的能力。同样,只要抹平系统接口差异,WebAssembly也能在其他操作系统中运行。因此,WebAssembly在web端可用于移植PC端应用,以及突破javascript性能瓶颈,实现web端CPU密级计算。同时WebAssembly也具备服务端应用能力,大有可为具备无限潜力!
看到这里,大家是不是会想,既然WebAssembly这么好,是不是可以取代javascript呢?其实所有技术都是对应具体的业务场景的。WebAssembly是一种编译领域新技术,实际上没有人会手写.wasm文件来进行编程,html+css+js仍然是web端开发主框架。一方面.wasm文件不易于持续开发和维护,另一方面,我们开发使用的web开源框架、第三方包目前基本都是基于js编写的,javascript是web页面不可取代的主流脚本语言。综上所述,我们要拥抱新技术带来的无限可能,也要根据实际业务场景选择适合自己的技术。
作者:潘梦圆
单位:中国移动智慧家庭运营中心