webassembly是一种底层的二进制数据格式和一套可以操作这种数据的JS接口的统称。我们可以认为webassembly的范畴里包含两部分
打破性能瓶颈
一直以来,我们都比较关心JS的运行速度问题,V8引擎解决了绝大多数情况下遇到的问题,但是少数情况下我们进行大量本地运算的时候,仍然可能遇到性能瓶颈,需要优化,这个时候webassembly的作用就凸现出来了
webassembly相对于纯JS的性能提升是随具体场景和条件的变化而变化的
当您使用WebAssembly时,不要总是期望得到20倍的加速。您可能只得到2倍的加速或者20%的加速。或者,如果您在内存中加载非常大的文件时,或者需要在WebAssembly和JavaScript之间进行大量通信时,那么速度可能会变慢。
作者:Robert 《Level Up With WebAssembly》一书的作者,同时也是一位生物信息学软件工程师
参考链接:https://python.freelycode.com/contribution/detail/1528
在上面的文章的作者Robert,做了这样一个实验,他使用 seqtk,一个用C编写的评估DNA测序数据质量(通常用于操作这些数据文件)的软件,去对比webassembly相对于普通JS带来的性能提升
一.Robert的对比测试结果
下面是他的测试结果
当然,上面的概括也许太过简略,大家可以看看Robert的原文以得到更为详细的认识
二.运行Fibonacci函数的性能对比
有位博主,对比了运行递归无优化的Fibonacci函数的时候,WebAssembly版本和原生JavaScript版本的性能差距,下图是这两个函数在值是45、48、50的时候的性能对比。
文章链接:https://segmentfault.com/a/1190000016949129
作者:detectiveHLH
三.IVweb的的性能对比测试
IVWeb团队对长度不同的文本进行加密处理,对比webassembly相对于纯JS的性能提升,结果发现
第一组测试:2M长文本100000 次加密处理
第二组测试:"ivweb"短字符加密100000 次
资料来源:https://zhuanlan.zhihu.com/p/79792515
从上面的资料中我了解到,webassembly性能提升的确存在,但是这个提升的范围是随条件和场景而变化的,需要遵循一定的原则
下面是我在can i use上查到的结果,可以看到在现代浏览器上兼容良好,覆盖率达到88%。主要的问题在于IE浏览器不支持(IE11)
IE兼容解决方案
Internet Explorer 11 是最后一个占有很大的市场份额,但不支持wasm的浏览器。我们可以通过 binaryen 项目的 wasm2js 工具,将我们的 WebAssembly 编译成 JavaScript,就可以获得 IE11 的大部分支持了
在浏览器中使用WebAssembly主要有两种方式:
备注:Rust是一门高性能的系统编程语言
参考MDN的这篇文档能够非常方便地跑起一个Demo
文章:《Rust 和 WebAssembly 用例》
地址: https://developer.mozilla.org/zh-CN/docs/WebAssembly/Rust_to_wasm
1.安装rustup,初始化Rust环境,它会顺带安装cargo等工具(相当于前端的Node安装)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
2.安装编译工具wasm-pack(相当于前端的babel)
cargo install wasm-pack
3.创建一个文件夹,进入后运行下面代码,初始化一个Rust 项目
cargo new --lib hello-wasm
初始化的文件夹如下所示
4.修改lib.rs,改为以下几段Rust代码,这段代码的is_odd是一个判断数字是否为奇数的方法
extern
5.修改配置文件Cargo.toml
这个文件和我们的package.json有点像,我们就依样画葫芦,这个文件大概要写成下面这个样子
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["作者名"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
备注
6.运行以下命令进行编译转化
wasm-pack build --scope [自己的名字]
// My Example
wasm-pack build --scope penghuwan
编译开始
编译成功后,新增了pkg文件夹和target文件夹
让我们看看pkg文件夹下的文件有哪
7. 将包发布到npm
1.cd pkg
2.npm publish --access=public
8.安装刚刚发布的wasm模块,并通过webpack工具加载后,在浏览器运行以下代码
const
9.浏览器输出
1.首先要按照文档下载编译工具emscripten
https://emscripten.org/docs/getting_started/Tutorial.html#tutorial
备注:如果没有将source ./emsdk_env.sh写入到启动文件中的话,那么每次使用前都要在给定目录下运行一遍
2.创建一个文件h.c,写入以下代码
#include
3.用命令行编译它
emcc h.c -s WASM=1 -o h.js
生成文件如下图所示
4.运行生成的h.js,则可看到输出了Hello World
看了上面的案例,你可能会觉得有些奇怪:怎么我们没有涉及浏览器提供的webassembly的API呀?
其实是有的,只不过在工具编译的时候自动帮忙填写了一些API而已,我们看下上面从h.c编译出来的h.js的一些片段就知道了
下面我们就来介绍下怎么手动去写这些API
接口
>> WebAssembly.Instance
实例包含所有的 WebAssembly 导出函数 ,允许从JavaScript 调用 WebAssembly 代码.
对象属性
>> WebAssembly.Module
包含已经由浏览器编译的无状态 WebAssembly 代码,可以高效地与 Workers 共享、缓存在 IndexedDB 中,和多次实例化。
对象属性
参考链接: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance
方法
>> WebAssembly.instantiate
它是编译和实例化 WebAssembly 代码的主要方法
返回值: 一个Promise, resolve后的值如下所示
{
Example
fetch
参考文章:https://hacks.mozilla.org/2018/10/webassemblys-post-mvp-future/
之前我们已经说到,webassembly适用于JS难以解决的大计算量的应用场景,如图像/视频编辑、计算机视觉,3D游戏等等。在这些场景下,webassembly能够大限度地提高速度,弥补JS的缺陷和硬伤。
同时在另一方面,我们也需要认识到以下几点:
设计工具Figma
一般情况下,为了使用速度,设计工具都会选择Adobe等本地应用,而不会选择浏览器网页应用,而能够同时打开十几个画板也没有卡顿的Figma正在尝试改变这一认知,webassembly让它具有高效流畅的体验
白鹭游戏引擎
白鹭游戏引擎是一套HTML5游戏开发解决方案,它衍生了开发莽荒纪同名手游、梦道、坦克风云的等游戏,而利用 WebAssembly,白鹭引擎让游戏运行性能提升了300%。
OpenGL 图形引擎Magnum
Magnum 是一款数据可视化 OpenGL 图形处理引擎,也采用了WebAssembly支撑浏览器环境的应用
参考资料:https://my.oschina.net/editorial-story/blog/1615877