由于初次了解WebAssembly,所以对WebAssembly的环境安装以及对基本的c++文件的编写及js的引入进行一次简单的记录
WebAssembly环境安装
-
安装Emscripten SDK
参照 webassembly.org.cn/getting-sta… 进行安装,在安装emsdk的过程中如果参照文章提供的以下方式会报错,
$ git clone https://github.com/juj/emsdk.git $ cd emsdk $ ./emsdk install sdk-incoming-64bit binaryen-master-64bit $ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit可通过以下安装方式解决
$ git clone https://github.com/juj/emsdk.git $ cd emsdk ./emsdk install latest #or ./emsdk install sdk-incoming-64bit binaryen-master-64bit ./emsdk activate latest -
安装wabt(The WebAssembly Binary Toolkit--可在字节码和文本格式间相互转换的工具包)
- 依据github.com/WebAssembly… 按步骤进行安装
- 配置全局环境变量,进入wabt/bin文件中,输入pwd获取文件夹路径,将路径粘贴在bash_profile中,如下格式:export PATH=/Users/WASM/wabt/bin:$PATH
- source ~/.bash_profile使得修改立即生效
- 回到对应的fib文件夹输入wasm2wat fib.wasm -o fib.wat 如果文件夹生成了fib.wat即安装配置成功
c文件代码及引入
1.在fib.c文件写一个不经过优化递归实现的的斐波拉契函数如下
int fib (int n) {
if (n <= 0) return 0;
if (n <= 2) return 1;
return fib(n - 2) + fib(n - 1);
}
2.fib.cpp通过Emscripten编译成fib.wasm文件,通过
emcc fib.c -Os -s WASM=1 -s SIDE_MODULE=1 -o fib.wasm命令生成fib.wasm
SIDE_MODULE = 1
命令解析:https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone
其中注意SIDE_MODULE=1的设置可以使得c文件在编译的时候只编译基本的写法,不会链接libc(C的函数库),
编译出来的wasm文件只有191byte,而如果不设置SIDE_MODULE=1的话fib.wasm将会有10316byte,并且会由于文件过大会导致报错: WebAssembly.Instance is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.instantiate.
3.js中引入fib.wasm
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer()) //加载字节码
.then(bits => WebAssembly.compile(bits)) //编译字节码
.then(module => {
return new WebAssembly.Instance(module) });//实例化
};
loadWebAssembly('./fib.wasm')
.then(instance => {
this.$wasmModule = instance.exports; //将instanc暴露在全局变量中以供js调用
fib = instance.exports.fib;
console.time();
console.log('通过调用wasm计算fib(45)', fib(45))
console.timeEnd();
});
注意
如果直接打开fib.html会报错: Fetch API cannot load file:///Users/WASM/fib/fib.wasm. URL scheme must be "http" or "https" for CORS request.
原因是通过fetch API获取的本地文件,而fetch API访问的是网络请求即'http' or 'https',而访问的资源是本地文件file:///,所以会由于违反了浏览器同源策略进而报错。
可以通过建立本地服务器的方式解决
1.serve .(需安装serve, yarn global add serve)
2.python2 -m SimpleHTTPServer(需安装python环境)
性能对比
通过本地html引入fib.js文件并打开fib.html;
同时在Chrome浏览器中用js编写递归无优化的斐波拉契函数,两者对比可以发现在计算同样的fib(45)的时候,wasm相较于js在性能上快了将近一倍多。
总结
1.WebAssembly比js快因为通过引入wasm的方式节省了高级代码转变为字节码的时间,即Parser阶段和ByteCode Compiler阶段的时间;
2.在有较大计算量的前端场景下可以通过使用WebAssembly提升性能,在c文件中编写计算量大的函数且通过SIDE_MODULE=1等编译命令编译出独立的wasm模块供js调用
参考文献