5分钟看懂WebAssembly

2020 年 7 月 5 日 InfoQ
作者 | Mehdi Zed
译者 | 王强
策划 | 李俊辰
2019 年 12 月 5 日,WebAssembly 正式加入 HTML、CSS 和 Javascript 的 Web 标准大家庭。很多事情都会受益于这一全新的标准,并且它在浏览器中的性能表现是空前的。本文会用五分钟的时间介绍一下这个正在进行中的小变革。

本文最初发布于 jesuisundev.com 网站,经原作者授权由 InfoQ 中文站翻译并分享。

往 事

1995 年,Brendan Eich 用了不到 10 天就创建了 Javascript。那时,Javascript 的设计并非以速度见长。它基本上是用于表单验证的,同时速度非常缓慢。随着时间的流逝,它也在一天天变好。

在 2008 年,异军突起的谷歌推出了自己全新的浏览器:谷歌 Chrome。Chrome 内部有一个名为 V8 的 Javascript 引擎。V8 的革命性进步是对 JavaScript 的即时(JIT)编译。从解释代码到 JIT 编译的这种转变大幅提升了 Javascript 的性能,从而让整个浏览器的速度变得飞快。如此快的速度将催生 NodeJS 或 Electron 等技术,并推动 Javascript 迎来爆炸式增长。

在 2015 年,WebAssembly 首次发布,并提供了一个运行在 Unity 下的游戏的小型演示。那款游戏是直接在浏览器中运行的!

在 2019 年,W3C 使 WebAssembly 成为了新的 Web 标准。就像 V8 引擎一样,WebAssembly 即将带来全新的性能革命。它的身影已经出现在了 Web 的赛道上,枪声一响便遥遥领先。

什么是 WebAssembly?

WebAssembly(缩写为 wasm)是一种使用非 Javascript 代码,并使其在浏览器中运行的方法。这些代码可以是 C、C++ 或 Rust 等。它们会被编译进你的浏览器,在你的 CPU 上以接近原生的速度运行。这些代码的形式是二进制文件,你可以直接在 Javascript 中将它们当作模块来用。

WebAssembly 不能替代 Javascript。相反,这两种技术是相辅相成的。通过 Javascript API,你可以将 WebAssembly 模块加载到你的页面中。也就是说,你可以通过 WebAssembly 来充分利用编译代码的性能,同时保持 Javascript 的灵活性。

WebAssembly 这个名子有点误导人。WebAssembly 确实适用于 Web,但它的使用场景远不止于此!开发 WebAssembly 的团队为了能让它用在所有环境下,跨越了重重障碍才取得成功。我们已经看到了这样的案例:

https://github.com/wasmerio/wasmer

此外,有一个误解也是相当普遍的。WebAssembly 不是编程语言。WebAssembly 是一种中间格式,叫做字节码,其可作为其他语言的编译目标。这么说可能还是会让人云里雾里,我们来画些图具体解释一下。

它是如何工作的?

看到这张图片了吧?画的多棒啊。如果我说我是用 Photoshop 画的你信不信?管它呢,我们来看图中的内容。

  • 第一步:这里是你和你的开发技能。你使用 C 或 C++ 生成源代码(还可以使用其他语言)。这段代码应该可以解决某个问题,或者完成某段对浏览器中的 JavaScript 来说太过复杂的流程。

  • 第二步:你将使用 Emscripten 来做翻译。Emscripten 是使用 LLVM 构建的工具链,可将你的源代码编译为 WebAssembly。安装它之后,你可以通过几个简单的步骤快速编译任意内容,稍后我们会具体介绍。这一步完成时,你将得到一个 WASM 文件。

  • 第三步:你将在网页上使用这个 WASM 文件。在将来,你可以像其他 ES6 模块一样加载这个文件。现在它的用法稍微复杂一点,但并没有什么绕弯子的部分。

好的,下面我们该来点实战了。

Show me the code

首先,我们需要一小段 C++ 代码来编译。有些人会给你看这个运行在浏览器中的完整版暗黑破坏神 1 游戏的例子:

https://d07riv.github.io/diabloweb/

而我这里就用一个简单的示例吧,下面是一个添加两位数的函数。我们并不会用它来展示 C++ 的速度有多快,只是举例而已。
int add(int firstNumber, int secondNumber) {  return firstNumber + secondNumber;}
下面转到你选择的 Linux 发行版。第一步是下载并安装 emscripten。
# 安装依赖项(是的,你可以使用 python 的较新版本)sudo apt-get install python2.7 git# 通过一个 git 克隆获取 emscriptengit clone https://github.com/emscripten-core/emsdk.git# 下载,安装并激活 sdkcd emsdk./emsdk install latest./emsdk activate latestlsource ./emsdk_env.sh# 确认安装的内容可以正常运行emcc --version# 将这个 c++ 文件编译到一个 webassembly 模板emcc helloWebassembly.cpp -s WASM=1 -o helloWebassembly.html# 启动 HTML 并观察结果emrun helloWebassembly.html

上面是极客处理 wasm 的路子。还有一种更简单的方法。你可以转到这个站点:

https://mbebenita.github.io/WasmExplorer/

将你的 C++ 代码放在左侧。然后,你将在 WAT 部分中获得导出函数的名称。使用我之前提到的 add 函数代码:“_Z3addii”作为函数名称,我们会在稍后使用它。你只需点击 download 按钮,就可以获取 WASM 文件。非常简单!

现在,我们就可以让 WebAssembly 直接运行在浏览器中了,没有那么多麻烦的事情
<html>  <head>    <title>WASM test</title>    <link rel="stylesheet" href="/stylesheets/style.css" />  </head>
<body> <script> const getRandomNumber = () => Math.floor(Math.random() * 10000);
WebAssembly.instantiateStreaming( fetch("https://012q1.sse.codesandbox.io/wasm/add.wasm") ) .then(obj => obj.instance.exports._Z3addii) .then(add => { document.getElementById("addTarget").textContent = add( getRandomNumber(), getRandomNumber() ); });</script> <h1>Résultat du C++</h1> <p id="addTarget"></p> </body></html>

这样就搞定了。这个 html 网页允许你使用编译成 WebAssembly 的 C++!这里我们跳过所有 HTML 和简单易懂的部分,直接看第 11 行的 InstantiateStreaming 函数。正如 Mozilla 文档所说,这个函数使你可以通过一个简单的 fetch 来编译和实例化我们的 WebAssembly 模块。然后,我通过前面获取的函数名称来使用 add 函数,并用它替换一段 DOM。看到了吗,在你的浏览器内通过 Javascript 成功实现了 C++!多了不起的事情啊,我甚至还给你做了一个带有可运行演示的 codesandbox:

https://codesandbox.io/s/webassembly-en-5-minutes-012q1?fontsize=14&hidenavigation=1&module=%2Fpublic%2Findex.html&theme=dark

你肯定会说,怎么这么简单的东西做起来都这么复杂?没错。他们正在努力,准备在将来用一个简单的 import 替换掉 instantiation 的 JavaScript 部分。因此请耐心等待,不用太久的。

结  语

我们已经聊够了五分钟,所以就到这里吧。如果你想了解关于 WebAssembly 的更多信息,并且有充足的空闲时间:我推荐你阅读这篇出色的文章,更深入地探讨这个话题:

https://www.javascriptjanuary.com/blog/webassembly-neither-web-nor-assembly-but-revolutionary

最后,我期待着看到 Web 对其他语言敞开大门后能带来怎样的变化。WebAssembly 背后的潜力是不可小觑的,我等不及要用上速度更快的 Web 了!

作者介绍:

我是一名开发人员。现在我在蒙特利尔从事后端开发 /DevOps 工作。开发是我的一项爱好,我也会随便写点东西。我每天会发些 Twitter(https://www.twitter.com/jesuisundev/)。你也可以给我发邮件(admin@jesuisundev.com),或者订阅我的 newsletter(https://mailchi.mp/024d0ebb03ba/jesuisundev)!

参考阅读:

https://www.jesuisundev.com/en/understand-webassembly-in-5-minutes/

为你推荐

InfoQ Pro 是 InfoQ 专为技术早期开拓者乐于钻研的技术探险者打造的专业媒体服务平台。扫描下方二维码关注 InfoQ Pro即可在【充电计划】中获取技术 PPT 下载链接,每周更新哟~持续关注我们,还有更多技术分享活动与干货资料,就等你来!

点个在看少个 bug 👇
登录查看更多
0

相关内容

JavaScript 是弱类型的动态脚本语言,支持多种编程范式,包括面向对象和函数式编程。
专知会员服务
200+阅读 · 2020年9月1日
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
【牛津大学&DeepMind】自监督学习教程,141页ppt
专知会员服务
179+阅读 · 2020年5月29日
【2020新书】如何认真写好的代码和软件,318页pdf
专知会员服务
63+阅读 · 2020年3月26日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
179+阅读 · 2020年1月1日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
22+阅读 · 2019年11月7日
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
看完这篇,你也可以实现一个360度全景插件
前端大全
6+阅读 · 2019年5月23日
说说我的老同事,前端大神程劭非
余晟以为
17+阅读 · 2019年1月14日
我的if else代码纯净无暇,一个字也不能简化
机器之心
3+阅读 · 2018年12月28日
WebAssembly在QQ邮箱中的一次实践
IMWeb前端社区
13+阅读 · 2018年12月19日
2018年8月份GitHub上最热门的开源项目
算法与数据结构
3+阅读 · 2018年9月4日
前端高性能计算(4):GPU加速计算
前端大全
7+阅读 · 2017年10月26日
Arxiv
7+阅读 · 2018年12月10日
Arxiv
8+阅读 · 2018年5月15日
Arxiv
11+阅读 · 2018年4月8日
Arxiv
13+阅读 · 2017年12月5日
VIP会员
相关资讯
微信小程序支持webP的WebAssembly方案
前端之巅
19+阅读 · 2019年8月14日
看完这篇,你也可以实现一个360度全景插件
前端大全
6+阅读 · 2019年5月23日
说说我的老同事,前端大神程劭非
余晟以为
17+阅读 · 2019年1月14日
我的if else代码纯净无暇,一个字也不能简化
机器之心
3+阅读 · 2018年12月28日
WebAssembly在QQ邮箱中的一次实践
IMWeb前端社区
13+阅读 · 2018年12月19日
2018年8月份GitHub上最热门的开源项目
算法与数据结构
3+阅读 · 2018年9月4日
前端高性能计算(4):GPU加速计算
前端大全
7+阅读 · 2017年10月26日
Top
微信扫码咨询专知VIP会员