什么是webassembly
WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行(Chrome, Edge, Firefox, 和使用WebKit的浏览器), 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C/C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。
webassembly的优点
- 最大的优势就是性能,直接在浏览器运行编译完成的低级别的机器码会比jit的JavaScript有天然的优势。 WASM二进制代码的执行时间仅仅只比原生代码慢20%。
- 可移植,编译完成的机器码,可以在不同平台运行,因为运行环境就是浏览器。
- 多语言支持,可以让其他语言编写,然后运行在浏览器。目前c/c++,rust,golang,Swift,typescript,等等…(参见:https://github.com/appcypher/awesome-wasm-langs#assemblyscript)
浏览器的支持度
详见:https://caniuse.com/#feat=wasm
webassembly如何运行
可以使用其他语言,然后通过编译工具编译出机器码,然后在浏览器里面加载并运行。
目前对于 WebAssembly 支持情况最好的编译器工具链是 LLVM,还有一个易用的工具叫做 Emscripten,它通过自己的后端先把代码转换成自己的中间代码(asm.js),然后再转化成 WebAssembly,实际上它是基于 LLVM 的一系列编译工具的集合。
简单的hello world
官方提供了一个工具链,可以直接把c语言编译成wasm在浏览器运行,以类Linux环境为例:
下载安装工具
$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
编写一个hello world的C代码
hello.c
#include <stdio.h>
int main(int argc, char ** argv) {
printf("Hello, world!\n");
}
编译代码并运行
$ emcc hello.c -s WASM=1 -o hello.html
$ emrun --no_browser --port 8080 .
工具会启动一个web server,会展示一个页面,在console显示hello world
.
JS是怎么调用wasm
- 获取 .wasm 二进制文件,将它转换成类型数组或者 ArrayBuffer
- 将二进制数据编译成一个 WebAssembly.Module
- 使用 imports 实例化这个 WebAssembly.Module,获取 exports。
可以编写一个文本格式的wasm的s表达式(一种通用的方便跟踪和调试的wasm文本,详细介绍:https://en.wikipedia.org/wiki/S-expression ),可以通过:WABT(https://github.com/WebAssembly/wabt) 转成成二进制的wasm文件
simple.masm
;; simple.wasm
(module
(func $i (import "imports" "i") (param i32))
(func (export "e")
i32.const 42
call $i))
转化命令(需要安装wabt工具):wat2wasm simple.masm
编写HTML:hello.html
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>wasm</title>
</head>
<body>
<script>
var importObject = { imports: { i: arg => console.log(arg) } };
function instantiate(bytes, imports) {
return WebAssembly.compile(bytes).then(
m => new WebAssembly.Instance(m, imports)
);
}
fetch("simple.wasm")
.then(response => response.arrayBuffer())
.then(bytes => instantiate(bytes, importObject))
.then(instance => instance.exports.e());
</script>
</body>
</html>
更多的例子: https://github.com/mdn/webassembly-examples
要理解wasm主要还是要理解,执行过程,以及js的API,还有就是s表达式,对js暴露的方式,调用js的方式。
此外,如果要了解c/c++如何编译成wasm,需要看http://kripken.github.io/emscripten-site/index.html 或者 https://github.com/WebAssembly/binaryen