WebAssembly 与 Rust 综述

首先要说一句,WebAssembly 是一项极速发展的技术,互联网上流传的很多文章(17,18年所写)已经过时了。所以,请尽量查阅最新时间的相关描述文档。


WebAssembly 是什么


来看一下标准定义:

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

WebAssembly(缩写为 Wasm)是一种面向栈虚拟机的二进制指令格式,Wasm 被设计为一种可迁移的目标格式,可以作为 C/C++/Rust 这类高级语言的编译目标。这让 Wasm 能够被部署在 Web 客户端和服务端程序中运行。


WebAssembly被设计为可以和JavaScript一起协同工作——通过使用WebAssembly的JavaScript  API,你可以把WebAssembly模块加载到一个JavaScript应用中并且在两者之间共享功能。这允许你在同一个应用中利用WebAssembly的性能和威力以及JavaScript的表达力和灵活性,即使你可能并不知道如何编写WebAssembly代码。


Wasm 已经被 Firefox, Chrome, Safari, Edge 支持。


官方网页:https://webassembly.org/


Wasm 的特点:

  • 高效运行

  • 安全

  • 开放可调试

  • 开放Web平台的一部分



高效运行。Wasm 栈虚拟机指令被设计得非常紧凑,生成的二进制文件体积小,加载时间缩短。WebAssembly 目标是接近本地的执行速度,同时能利用不同平台的硬件能力。


安全。WebAssembly 提供了一个内存安全的沙盒执行环境。当在 Web 上使用时,WebAssembly 会强制使用浏览器的同源和权限安全策略。


开放可调试。WebAssembly  在使用时,编译出来为二进制文件。但是它同时也被设计为一种方便人阅读的文本格式(根据不同的编译选项)。用这种格式,人们可以调试、测试、实验、优化、学习、教授甚至手写  WamAssembly 源文件。当需要在 Web 查看 Wasm 模块的源代码时,就是用这种格式查看。


开放Web平台的一部分。WebAssembly 兼容了之前Web的操作方式,可以在 JavaScript 中调用,也可以访问浏览器提供的功能(使用同一个 Web APIs)。WebAssembly 还支持非Web的运行环境。


Wasm 是一项极速发展的技术,网络上的任何介绍任何心得体会都会快速过时,所以,一切以官方网站信息为准。这是官方给出的路线图文档,可以了解其发展方向和节奏。


哪些语言可以编译到 WebAssembly


现在很多语言都可以将 WebAssembly 作为它的编译目标了。但是不同的语言编译的成熟度不同。目前最高成熟度的语言有几个:C/C++/Rust。下面是一个不完整列表:

WebAssembly 与 Rust 综述

小鸡分成三种状态:还是个蛋,还在壳中,完全出来。可以看到,成熟的并不多。

查看详情,请点击这里。


为什么最佳是 Rust


因为 Rust 是 Mozilla 亲儿子啊。记得 Js 是谁的亲儿子不?也是 Mozilla(的前身,网景)。WebAssembly 标准是谁主导的?还是 Mozilla。


上面虽然是玩笑,但是也能暴露出其内在原因:Mozilla 为什么同时全力在推 WebAssembly 和 Rust。


下面说说技术型原因。


为什么不是 Go 或 C#


为什么不是语法更简单的 Go 语言 或者生态更成熟的 C# 更适合编译到 WebAssebmly 呢?


其实最核心的问题,跟语法什么的,没有任何关系。最关键就是 Runtime 大小的问题。Go 维基上说,一个最简单的  Go 程序编译到 Wasm 后,未压缩的目标文件大小最小为 2MB。而 Rust,由于其极小 runtime(与 C/C++  差不多),一个最小的 “Hello, world” 程序,编译出来的 Wasm 目标文件大小为 1.6KB,还可以继续优化。

而 Runtime 大小的核心就是 GC。一个带 GC 的语言,其 runtime 不会小到哪里去。这就是问题的根本了。也可以说这是基因决定的,不太可能随着时间的流逝而有突破性的改变。


要知道,如果要从 Web 上加载 Wasm,一个 2MB 的文件是一个相当大的负担。


为什么不是 C/C++


那为什么不是 C/C++ 呢? C/C++ 同样没有 GC,runtime 也极小。为什么选择 Rust 而不选择 C/C++?


第一,是因为 Rust 是安全编程。这个概念所有的 Rust 资料都在强调,故此处不再赘述。编程安全,心智负担就小,写起来心情轻松。


第二,Rust 比 C/C++ 开发效率高。因为 Rust  融合了一些函数式语言的语法特性。所以写起来舒服,抽象层次高,开发效率高。抽象高的同时,编译出的目标,运行效率还与 C/C++  持平,那你说选谁。一般来说,爱上 Rust 的程序员,就很难再回头去写 C/C++ 了。


第三,Rust 生态更完善。这个也跟亲爹是 Mozilla 有关系。C/C++ 不是不可以做大量 Wasm  相关的生态工具。但是没有组织积极地去推动。整个 WebAssembly 生态,只有 Mozilla  是全力推动生态工具的建设,而这些工具,都是针对 Rust 的。这些工具有:


  • wasm-bindgen

  • wasm-pack

  • gloo

  • twiggy

  • book

  • web-sys

  • js-sys


等等。


这些工具链,让 rustwasm 官方工作组和社区付出了巨大的精力。它们还在快速迭代中。


有了这些武器加持,再加上强力的 Cargo,现在使用 Rust 进行 WebAssembly 开发,已经很轻松了。从生态完整度来说,Rust WebAseembly 已经遥遥领先。


不过,整个 WebAssembly 生态都还处于极早期,未来还有很长的路要走。Rust 将在这个方向上发出更耀眼的光芒。


使用 Rust 为 Web 提速


请参见 使用 Rust 进行前端 Web 开发 第一节。


使用 Rust 为 Nodejs 提速


请参见 使用 Rust 进行前端 Web 开发 第三节。


注意,这个技术方向不是使用 Rust 为 Nodejs 写本地扩展模块(比如 Neon)。而是把 Rust 代码编译成 .wasm 文件,然后在 Nodejs 中调用。


WASI,一个新纪元


2019年3月,Mozilla 提出了 WASI (WebAssembly System Interface)。这是一套让  WebAssembly 在 Web 浏览器外运行的接口规范。你可以把它认为是一个跨平台的 libc 接口规范。现在还在设计 WASI Core  规范。

WASI 的提出,可以说是一个新纪元。WebAssembly 虽然是为 Web  浏览器加速而设计的,但是其在设计之初就定下方向说,它不仅可以运行在浏览器中,还可以运行在浏览器外。运行在浏览器外,就是说,可以运行在所有计算设备上。它是跨平台的解决方案。这让我们想起了25年前,Java的目标“一次编译,到处运行”。而由于 Wasm 精密高效的设计,这个目标被重新提了出来。


目前的几个 WASI 项目介绍


Wasmtime

wasmtime 是一个 Wasm JIT 运行时。由 Mozilla 下属的 Crane Station 主导开发。


WASI 和其文档规范的提出,就是 Wasmtime 项目做的。可以认为是这官方的运行时。


但是也许官方的不一定是最好的。


Lucet

Lucet 是一个原生 Wasm 编译器和运行时,由 Fastly 出品。


Fastly 已经把 Lucet 用在了其边缘计算云服务产品上了。目前在紧跟 WASI 规范,对其做支持。


这是它的发布公告


Wasmer

Wasmer 通用 WebAssembly 运行时。它的野心很大,要让 wasm 运行在任何地方。


目前 Wasmer 正在做 WASI 规范的兼容。


  • php-ext-wasm: Migrating from wasmi to Wasmer  比 wasmi 虚拟机提高 29 倍的速度。

  • Running WebAssembly from any language

  • Repo


由于 WASI 是一项极速发展的技术,我们在此说得越多,过时就越快。作为一家专业媒体,最好的方式就是引导大家到达最正确的信息源。


更多细节

Q:Wasm 有 gc 不?
A:No。Wasm 本身的标准是没有 GC 实现的(未来有提供其基础设施支持的计划,详见GC Extension),所以带 GC 的语言要编译到 Wasm 上,需要带一个相对很重的 runtime,由 runtime 实现 GC。


结语


WebAssembly 正在开启一个新的未来,而 Rust 语言就是这个新的革命战场上的主力正规部队。一切都在快速发展中,我们需要尽快投入。


上一篇:基于wasm技术的H.265网页播放器设计理念


下一篇:WebAssembly 实践:如何写代码