当前位置:首页 > 科普 > 列表 > 正文

什么?在浏览器上跑C++!
2024-09-24

近年来,随着浏览器朝着第二操作系统的目标突飞猛进,我们可以发现越来越多的桌面应用被移植到了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页面不可取代的主流脚本语言。综上所述,我们要拥抱新技术带来的无限可能,也要根据实际业务场景选择适合自己的技术。

作者:潘梦圆

单位:中国移动智慧家庭运营中心

开通会员,享受整站包年服务立即开通 >