前言
背景
在介绍WebAssembly
,我们先对发展历史做一个介绍。
话说JS
诞生之时,只是作为一个胶水用的,能缝缝补补就行,后来发现好像挺重要的,于是就改吧改吧,用着用着还算可以,在JIT
技术和v8
引擎没出来是,JS
勉强能用,但是面对大需求就不是很好了.
于是各大厂商都准备推出自己的解决方案了,Google
的Dart
,Firefox
的asm.js
,MirroSoft
的TypeScript
,但是各有各的缺陷,同时v8
使得js
焕发了第二春,同时各大平台没有的统一的规范也不是很好,于是乎WebAssembly
出世了
编译原理
JS
之所以运行慢是因为,浏览器的JS引擎是需要边解释边运行的,同时作为弱类型,在很多优化也不是很好,虽然有JIT
优化,但是速度还是堪忧
WebAssembly是什么?
WebAssembly使用C语言(或TS等等)编写经过编译成字节码而成的,在浏览器中,相当于可以直接编译成机器码,几乎可以直接运行
- 生成WebAssembly的C代码:
// c
int add42(int num){
return num + 42
}
// ts
export function f(x: i32): i32 {
if (x === 1 || x === 2) {
return 1;
}
return f(x - 1) + f(x - 2)
}
- WASM Explorer编译成c字节码,asc编译ts
00 61 73 6D 0D 00 00 00 01 86 80 80 80 00 01 60
01 7F 01 7F 03 82 80 80 80 00 01 00 04 84 80 80
80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06
81 80 80 80 00 00 07 96 80 80 80 00 02 06 6D 65
6D 6F 72 79 02 00 09 5F 5A 35 61 64 64 34 32 69
00 00 0A 8D 80 80 80 00 01 87 80 80 80 00 00 20
00 41 2A 6A 0B
- 加载.wasm模块到JavaScript MDN文档
fetch('f.wasm') // 网络加载 f.wasm 文件
.then(res => res.arrayBuffer()) // 转成 ArrayBuffer
.then(WebAssembly.instantiate) // 编译为当前 CPU 架构的机器码 + 实例化
.then(mod => { // 调用模块实例上的 f 函数计算
console.log(mod.instance.add42(50));
});
编译过程对比
相对于JS
20-1
- Parsing - 源代码解释成运行代码
- Compiling+optimizing - 编译和优化阶段
- Re-optimizing - JIT假设优化出错,丢弃优化,重优化重编译
- Exection - 执行
-
Garbage collection - 垃圾回收
而WebAssembly
20-3
WebAssembly的优势
- 文件抓取阶段,WebAssembly因为是字节码所以体积比js小很多
- 解析阶段,解析时间更短
- 编译优化执行阶段都是WebAssembly更具有优势
相关
参考资料
WebAssembly 现状与实战
深入浅出 JIT 编译器
WebAssembly 系列
WebAssembly 官网
网友评论