Skip to content
字数
1797 字
阅读时间
7 分钟

先看一张图,言简意赅

JS 运行机制的缺陷

javaScript 是一门动态类型的语言,编写程序时无需考虑变量类型,而且还可以运行时改变类型。对于我们开发者,确实很方便,但对于运行它的引擎就很有问题了。参考这里的一张图,看一下 V8 引擎从 js 源码到执行的一个过程

性能缺陷

由于 js 的动态类型,解释器在执行代码的时候会在类型判断上带来一定的性能消耗,降低执行速度。所以 V8 引擎采用了 JIT(即时编译技术) 技术,监控一些经常执行的代码,将其编译成 CPU 直接执行的机器码,提高执行速度。但由于 js 动态类型,在某些情况下还得反优化,回到字节码进行执行。

随着前端的不断发展,项目的大小和复杂度不断增大,对于某些场景,性能上可能已经无法满足,浏览器厂商们也一直在探索性能优化的方法

衍生的技术方案

NaCl/PNaCl

2011 年 Google 在 Chrome 中使用了 NaCl 技术,可以使得 C 语言编写的程序运行到浏览器中

Google Native Client(缩写为NaCl),是一个由 谷歌 所发起的 开放源代码 计划,采用 BSD许可证。它采用 沙盒 技术,让 Intel x86ARMMIPS 子集的 机器代码 直接在沙盒上运行。它能够从 浏览器 直接运行程序机器代码,独立于用户的操作系统之外,使 Web应用程序 可以用接近于机器代码运作的速度来运行,同时兼顾安全性。其功能类似于 微软 的 ActiveX,但是 ActiveX 只支持视窗系统。

但一个完整的 NaCl 应用,在分发时需要提供支持多个架构平台(X86 / X64 / ARM 等)的模块文件,后来谷歌又推出了与底层架构无关的 PNaCl 技术。但由于其开发难度、兼容性等问题最终没有普及开来。在 2017 年 Google 宣布放弃 PNaCl 转向 WebAssembly

ASM.js

ASM.js 是 Mozilla 在 2013 年推出的,是 javaScript 的一个严格子集,可以作为 C/C++ 编译的目标语言,从而使得 js 引擎可以采用 AOT(Ahead Of Time) 的编译策略,也就是在运行前直接编译成机器码,因此运行速度会有一定的提升。

ASM.js 通常不直接编写,而是作为一种通过编译器生成的中间语言,该编译器获取 C++ 或其他语言的源代码,然后输出 ASM.js

例如下边的 C 语言代码。

c
int f(int i) {
  return i + 1;
}

经过编译器编译会生成下边的 js 代码。

js
function f(i) {
  i = i|0;
  return (i + 1)|0;
}

注意这里的 |0 在 js 中相当于和 0 进行了或操作,所以不影响原本的逻辑。在 asm.js 中起到了类型标记的作用,这样 js 引擎执行的时候就知道 i 是一个整型,返回值是一个整型。除了或操作这种,ASM.js 标准中还规定了很多类似的标记规则,用于告诉 js 引擎变量的类型,便于进行 AOT 优化。

这看起来和 TypeScript 很像,但其实不是一种东西。TypeScript 是 js 的一个超集,浏览器并不能直接执行 ts,还需要转换为 js 去执行。ts 主要是帮助我们开发人员去看的,增加了代码的可读性,也可以让编辑器提前发现一些错误。而 asm.js 是用于引擎的编译优化。

WebAssembly

再之后便是 WebAssembly

具体使用参考 开发者引导 - WebAssembly 中文网|Wasm 中文文档

具体应用

eBay 的条形码扫描

eBay 在原生应用中有专门的 C++ 库用于条形码的扫描,在 H5 中利用开源 JavaScript 库 BarcodeReader 做了一个带条形码扫描功能的 Web 版本。 问题是它只有在 20% 的时间表现良好。 剩余的 80% 的时间运行非常缓慢,准确率也不高。

最终的解决方案是通过 wasm ,将原有的 c++ 库引入,以及业界十分有名的、基于 C 语言编写的开源条形码扫描库 ZBar 引入,再加上原本的 js 库,三者协助,最终识别率达到了 100%

AutoCAD

最初基于 C++ 编译为 Java 代码供 Android 设备使用,最后,在 Google Web Toolkit(一个 Google 开发的可以使用 Java 语言开发 Web 应用的工具集)的帮助下,又将这些 Java 代码转译为了 Web 平台可用的 JavaScript 代码。但最后生成的 Web 应用代码库十分庞大,且在浏览器中的运行性能并不可观。这个「粗糙版」的 Web 应用发布于 2014 年。

2015 年通过 Asm.js 将原有的 C++ 代码中的主要功能直接进行编译移植到到 Web 平台,性能有了很大的提告。2018 年 3 月,基于 Wasm 构建的 AutoCAD Web 也成功诞生,https://web.autocad.com/login

bilibili 视频封面

投稿视频的时候,当你的视频还在上传中,已经可以自由选择 AI 推荐的封面。这里采用了 webassembly+AI 的前端整合。

  1. webassembly 负责读取本地视频,生成图片;
  2. tensorflow.js 负责加载 AI 训练过的 model,读取图片并打分。
  3. 从完全的服务端架构 => 前端架构 && 服务端兜底。

webassembly 支持解析 99% 以上的视频编码格式,速度提升体验惠及约 50% 的 web 投稿用户。

不止于 Web

Wasm 除了应用在浏览器中,也可以应用到 out-of-web 环境中。通过 WASIWebAssembly System InterfaceWasm 操作系统接口)标准,Wasm 可以直接与操作系统打交道。
通过已经在各种环境实现了 WASI 标准的虚拟机,我们就可以将 wasm 用在嵌入式、IOT 物联网以及甚至云,AI 和区块链等特殊的领域和场景中。

比如一款 A 应用,如果想实现跨平台的话,我们需要用 java 完成在安卓上的开发,用 Objective-C 实现 iOS 上的开发,用 C# 实现 PC 端的开发... ...也就是下边的样子。

但如果有了 wasm ,我们只需要选择任意一门语言,然后编译成 wasm,就可以分发到各个平台上了。

转载

WebAssembly入门

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写