现代浏览器朝着第二操作系统一路狂奔,网页在线 PS、3D 地图、音视频编解码、游戏引擎等等应用,都在浏览器实现了,这都是基于 WebAssembly。
什么是 WebAssembly
WebAssembly 也简称 wasm,是以.wasm 结尾的文件。我们都知道,在机器的世界,最终运行的都是 0101 这样的二进制文件,而 WebAssembly 是被编译成二进制的文件。WebAssembly 并不是一门语言,而是一个编译的目标,好比我们用 vite、gulp、rollup、webpack 等打包成最终的产物,WebAssembly 是把其它编程语言编译成二进制文件,从而可以运行在浏览器上,实现更复杂的应用。
起源
说起 WebAssembly 不得不提起 Mozilla,一个非营利性的开源组织,致力于推动开放式网络和互联网技术的发展,Rust、HTML5、MDN、asm.js 等互联网行业基石都是这家公司的产物,前身是网景公司(Netscape Communications Corporation)。
当初 Emscripten 项目的创造者 Alon Zakai 开始研究将 C/C++ 代码编译为 JavaScript 的想法时,他的初衷并不是为了在 Web 浏览器中运行高性能代码。实际上,他的目标是为了在 Node.js 环境中运行 C/C++ 代码。
然而,当 Alon Zakai 开始探索将 C/C++ 代码转换为 JavaScript 的方法时,他发现 JavaScript 引擎在 JIT(即时编译)时的优化能力非常出色。这让他想到,如果能够通过一种方式将 C/C++ 代码转换为符合特定规范的 JavaScript,那么 JavaScript 引擎就可以通过 JIT 编译来优化和加速这些代码的执行。
于是,Alon Zakai 开始着手开发 Emscripten,并提出了 asm.js 这种低级子集 JavaScript 的概念。他利用 LLVM 编译器作为后端,将 C/C++ 代码编译为符合 asm.js 规范的 JavaScript。
asm.js 可以说是 WebAssembly 的前世,Emscripten 官网有介绍:
Compile C and C++ code, or any other language that uses LLVM, into WebAssembly, and run it on the Web, Node.js, or other Wasm runtimes.
除了 C C++,其它只要是能使用 LLVM 的都能编译成 WebAssembly。
JavaScript 在运行过程中,需要编译成引擎能够直接执行的字节码,在此过程会对执行次数较多的代码进行优化,下次再次执行的时候直接使用上一次编译完成的字节码,但由于 JavaScript 本身是弱类型语言,上次是 string,下一次可能就是 boolean 了,上一次的优化也就失效了,又得重新编译执行,在效率方面肯定就会低一些。于是 asm.js 出现了。
asm.js 会强制静态类型,所以会比原生 JavaScript 更快一些,这个快要根据实际场景,我们说的是在正常的普遍的时候,不以极端场景来说。当然,asm.js 更重要的是让 C 和 C++等语言也可以运行在浏览器上。
WebAssembly 诞生与优势
asm.js 的思想是一个语言编译成另一个语言,输出的还是 JavaScript,不过强制了静态类型,还是需要经过编译。于是,跳过编译可以直接运行的 WebAssembly 就诞生了,WebAssembly 是浏览器可以识别的更底层的语言。WebAssembly 不是具体的开发语言,而是各个语言编译成 WebAssembly,然后运行在浏览器内置的 wasm 虚拟机中,除了运行在浏览器,WebAssembly 也能运行在很多地方,是一种新的二进制指令集格式,它是一种可移植、高性能的代码格式,对于很多语言来说都是支持运行的。
WebAssembly 提议于 2015 年推出,早期版本于 2017 年推出,在 2019 年 12 月 5 日成为 Web 标准。现在的浏览器几乎都兼容 WebAssembly。
WebAssembly 主要有几点优势
体积更小:WebAssembly 的二进制格式在被精心设计之后可以比 gzip 压缩后的 JavaScript 代码小 10-20%左右。
高性能:WebAssembly 得益于其二进制的格式,可以通过即时编译器(JIT)或预编译器进行优化,从而提供更高的执行速度和更低的延迟解析速度,比 JavaScript 快了一个量级,还可以在多核 CPU 上进行并行解析
跨平台,Wasm 是一种与平台无关的代码格式,可以在不同的 Web 浏览器和操作系统上运行。这意味着开发人员可以使用不同的编程语言(如 C/C++、Rust 等)编写代码,并将其编译为 Wasm,然后在不同的平台上部署和运行,无需重新编写或适配代码。这提供了更大的灵活性和可移植性
安全性:由于 Wasm 的执行是在沙箱环境中进行的,它具有更高的安全性。Wasm 代码受到严格的安全限制,只能访问特定的资源和 API,并且与宿主环境(如浏览器)之间有明确定义的接口。这限制了恶意代码对系统的潜在危害,从而提供了更好的安全性
生态系统支持:Wasm 在 Web 开发社区中得到了广泛的支持和采用。已经有许多工具、编辑器、框架和库提供了对 Wasm 的支持和集成,使开发人员能够更方便地开发、调试和优化 Wasm 代码。
WebAssembly 在性能方面只是最基本的,更大的作用体现在给 web 提供了更大的可能和发展,不仅是 C++、RUST(编译优化程度会更高),PHP、GO、Python 等也都能实现。
WASI
需要明确的是,WebAssembly 的宏图绝不是只运行在浏览器,脱离了浏览器后,运行在各个操作系统中只需要抹平系统 api 的差异性,WASI 就诞生了。
WASI(WebAssembly System Interface)是一个开放标准,旨在为 WebAssembly 提供一个通用的系统接口,使其能够在各种计算平台和操作系统上运行。WASI 的目标是提供一套标准的 API,使 WebAssembly 模块能够访问底层系统资源和功能,例如文件系统、网络、进程管理等。
WASI 的设计初衷是为了解决 WebAssembly 在不同平台上的兼容性和可移植性问题。通过提供统一的系统接口,WASI 使得开发者可以编写与特定操作系统无关的 WebAssembly 模块,从而实现跨平台的部署和执行。
WASI 的工作原理是通过与底层操作系统进行交互,将 WebAssembly 模块的系统调用映射到相应的底层系统调用。这样,WebAssembly 模块就可以在不同操作系统上以相同的方式访问系统资源,而无需关心底层操作系统的细节和差异。
WASI 是由多个技术组织和公司共同推动和开发的,包括 Mozilla、Fastly、Google 等。WASI 标准的开发和演进是一个开放的过程,任何人都可以参与其中。
通过 WASI,WebAssembly 的应用场景得到了扩展,使得开发者可以更轻松地将 WebAssembly 模块应用于更广泛的领域,包括服务器端应用、嵌入式系统、边缘计算等。
只是相对来说,各个语言对于常用的场景来说,性能限制都不会像 web 限制那么大,所以 Java 能实现的,PHP 大部分也能实现,就不太需要那么多通过编译出 WebAssembly 然后到 PHP 运行实现。
Emscripten
我们一直说 WebAssembly 不是一门语言,开发者并不需要去手动敲一行一行的 WebAssembly,大部分都是使用 Emscripten 进行编译,Emscripten 说是 WebAssembly 的灵魂工具不为过,WebAssembly 的前身都是因为 Emscripten 而诞生。
Emscripten 是一个开源工具链,用于将 C 和 C++等编程语言的代码编译为 WebAssembly(Wasm)和 JavaScript,使其能够在 Web 浏览器中运行。它是使用 LLVM 编译器框架构建的,可以将 C/C++代码转换为高效且可移植的 WebAssembly 字节码。
Emscripten 已经被广泛应用于各种领域,包括游戏开发、图形渲染、数据可视化等。许多知名的项目和游戏,如 Unity、Unreal Engine、Google Earth 等,都使用 Emscripten 将其代码转换为 WebAssembly,以实现在 Web 浏览器中运行。
在 web 端的应用
Google Earth,需要展示很多 3D 的图像,对性能要求非常高,最早只能是下载桌面版,现在在浏览器就能直接使用Earth
AutoCAD,AutoCAD 是用 C++实现的,WebAssembly 出现之后,AutoCAD 得以利用编译器,将其沉淀了 30 多年的代码直接编译成 WebAssembly,同时性能基于之前的普通 Web 应用得到了很大的提升
Unity 和 Unreal 游戏引擎,目前所有版本的 unity 以及 Unreal4.18 之前版本的 UE,都支持将游戏内容打包发布到 web 端。之后的版本不支持,就不知道为什么了。
FFmpeg-音视频处理,这个可能是大部分知道 WebAssembly 的在 web 端应用非常广的一个应用了。ffmpeg.wasm,太多的应用都是在这个的基础上套了一个 UI。
Adobe Photoshop Web 版,WebAssembly 解决了很多性能问题,更重要的是 Photeshop 的 web 端和 PC 端应用可以由同一份源码编译生成,对于简单的需求,肯定是不希望安装 Adobe Photoshop(对于我来说,安装或者破解都要好一番折腾)。
其实还有很多很有名的应用都在 web 上实现了,很大程度也都是基于 WebAssembly,比如 SketchUp、AutoDesk Fusion 360、Microsoft Office、Figma-设计工具、Zoom-在线会议等等。
WebAssembly 的意义
WebAssembly 给了 web 更好的性能,给了 web 更多的可能,把更多 Desktop 的应用搬到 web 上,改变了 Web 应用的发展方式和能力,提供了更高性能、跨平台、多语言支持和更安全的 Web 开发体验。它使得开发者能够在 Web 平台上构建更强大、复杂和创新的应用,同时为用户提供更好的使用体验。
只是可惜的一点是,有很多应用能够在 web 实现,WebAssembly 是其中一个重要的点,但是 webGL 渲染器的改进却是更重要的一点,虽然目前很大很大的场景并不需要 WebAssembly,但是不能否认 WebAssembly 会在未来扮演很重要的角色。
我会想要了解 WebAssembly,是因为业务扫码遇见了问题,使用 zxing 扫码的时候,如果码贴近标签的边缘,贴在深色的物品上面,会无法解析。通过拍照生成图片去解析,把生成的图片黑白通过 rgb 转换,都不能解决。最后是我们的 leader 用 Java 版本写了接口试了一下可以了,然后就使用 Java 版本生成的 wasm 实现了。
我第一次知道 WebAssembly 的时候,也觉得是不是未来的风向标,是不是一定要去学一下,后面觉得吹的有点过头了,其实目的就是营销,对于前端来说,只需要找到 wasm 文件,找到文档,使用它,目前我是觉得不需要去学习。
文章里面用了蛮多chatgpt搜索出来的东西,也是最近才发现,3.5的已经不限制账号了,连地区也不限制了,不用登录都能直接用:https://chat.openai.com/
欢迎关注订阅号 coding个人笔记