背景
WebAssembly 简称 Wasm,最早起源于前端技术。
即使在有了 JIT 加持之后,js 在大计算量的场景,性能还是不够理想,经过了 asm.js 的尝试,最后以 Wasm 定型,得到了四大浏览器的支持。
最初的 Wasm 主要是应用于 WEB 应用,后续随着 WASI 的诞生,又扩展到了更宽的场景,比如服务端技术。
Wasm 是什么
Wasm 并不是一门常规意义上的语言,而只是一个基于栈式虚拟机的二进制指令标准。
比如,Lua 是一门语言,因为其具有可编程能力,而 Lua 字节码,则几乎不具备可编程能力(一定要手写也不是不可以)。
Wasm 就类似于 Lua 字节码这种位置,只是它更相对更底层一些,适用范围也更广。
Wasm 设计目的,就是成为其他语言的编译目标,目前支持比较好的有 C/Rust 等。
Wasm 如何运行
由于 Wasm 只是一个标准,具体的执行是由虚拟机来完成的,而虚拟机的实现就又有很多个,类似于官方 Lua 与 LuaJIT 这种。
具体的运行方式也有多种:interpreter,JIT,AOT。比较有意思的是,在 Wasm 圈里,似乎 AOT 技术相对其他语言更流行一些。
具体的虚拟机实现细节,我们可以以后再介绍了。
Wasm 的特点
Wasm 有优秀的设计理念,有其明显的优势,不过优势有时候也需要付出一些代价。
高性能
这是 Wasm 的设计初衷之一,是有接近 native 性能的,当然也依赖虚拟机的具体实现。
从指令设计上而言,Wasm 足够底层,简单,所以理论上是可以接近 native 性能的。
内存安全
Wasm 被设计为内存安全的,尤其在 WEB 场景,很多时候执行的代码都不知道来自谁,底层安全是很重要的。
具体而言,Wasm 的内存模型很简单,只有一个 linear memory,Wasm 能操作的内存的读写都发生在这个 memory 范围内。
Wasm 是不会出现指针飞来飞去的,有的只是 offset
,目的是恶意的 Wasm 执行的时候,也不可能读写进程内任意的数据内存。
当然咯,代价也是有的,灵活性会有一些折扣,很多时候需要多一次内存拷贝。
沙箱
Wasm 是运行在一个沙箱环境,其所具备的能力是受限的,需要的一些外部调用,是外面的宿主提供给它的。
比如 Wasm 需要读文件,那也是需要运行 Wasm 的宿主环境,给其提供对应的 API 才可以的。
跨语言
跨语言是 Wasm 的一大亮点,依我之见,可以某种程度上的降低语言之争(语言之争,其实也是个蛮有意思的话题,得空可以聊一聊)。
Wasm 作为中间的标准产物,可以对接两头的开发者:
- 上层的应用开发者
- 底层的服务开发者
底层服务开发者,只需要为其提供运行 Wasm 的沙箱环境,包括运行 Wasm 的虚拟机,以及暴露服务的某些能力在沙箱中。
上层应用开发者,则可以选择自己喜欢的语言,以及对应语言的 Wasm-SDK(对应暴露在沙箱中的服务基础能力)即可生成 Wasm。
理论上是一个美好的方案。
最后
Wasm 也是一种嵌入式的方案,某种程度上跟 Lua 很类似。
依我之见,少年期的 Wasm 还有比较长的一段路要走
- 底层的能力还有待增强,比如带 GC 的语言,生成 Wasm 就是一个难题。
- 周边生态也有待发展,目前还属于初级阶段,虽然能看到一些设计雏形。