WebAssembly 学习笔记

第一次听到 WebAssembly 的是来自于同事,他描述了一种不通过 JavaScript编程语言也能够实现前端开发的方式。刚听到的时候很惊艳,想到前端开发竟然可以避开JavaScript,简直神乎其技,但究竟如何实现的,又感觉很模糊。

最近总是听到 WebAssembly,网上总是在描述它是浏览器中 JavaScript 的替代品。并且能够提供比 JavaScript 更高的性能诸如此类的话题。由于这个类说了又好像没有说的话,导致我对这个概念很模糊。今天抽空做了解。


概念

什么是 WebAssembly

WebAssembly/wasm WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式

^来源:WebAssembly 中文网

WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。

^来源:WebAssembly MDN

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

^来源:WebAssembly

类汇编语言(二进制)

不同于JavaScript的解释执行,WebAssembly使得浏览器能够以二进制格式运行代码。由于更接近于汇编语言,所以在网络中传输效率和执行效率都比JavaScript要高。但是另一方面由于WebAssembly是一种紧凑的二进制格式,因此我们无法直接编写WebAssembly代码,而是需要借助其他语言如(C、C++、Rust)等编程语言借助工具后编译为 WebAssembly语言后才能使用。

了解到这里,WebAssembly 给我的感觉就像是在浏览器上运行的 JVM。它将原本在浏览器上JavaScript直接解释执行在 JavaScript虚拟机上的这个流程打破了,然后在中间像 Java 一样加了一层。
WebAssembly 学习笔记_第1张图片
有什么好处呢?

首先,编译后的二进制文件要远远比源代码小,这就会使得请求.wasm文件要比请求.js文件速度要快;

另一方面,浏览器在执行二进制文件时可以避免解释执行的步骤,从而使得执行速度大大提升。可以类比 Java 程序执行速度没有C程序的执行速度高,原理是一样的。

但是,这样做带来的问题也很明显,编译后的代码不易于调试,而且由于中间多了一道供需,使得代码出错的几率也相对提高了。
WebAssembly 学习笔记_第2张图片
除此之外 WebAssembly 还是给我们提供了另外一种可能,是 JavaScript 之外的更多的可能性。

入门使用

环境准备

  • git ,ubuntu下apt install git 安装
  • cmake , ubuntu下 apt install cmake 安装
  • gcc , ubuntu下 apt install gcc 安装
  • python ,ubuntu 下 apt install python 安装

安装完成后,确认 git,cmakepython 已经在你的环境变量中可以使用。
安装 Emscription
通过 git 克隆 Emscripten 仓库,然后执行命令即可完成安装:

> git clone https://github.com/emscripten-core/emsdk.git
# 国内环境可以使用镜像
# git clone https://gitclone.com/github.com/emscripten-core/emsdk.git
> cd emsdk
# 安装 emsdk
> ./emsdk install latest
# 激活 emsdk
> ./emsdk activate latest
# 配置环境变量
> source ./emsdk_env.sh

注意安装过程需要 gitcmakegcc等工具,如果这些工具在系统中缺失的话会导致一些错误;此外在安装成功后需要激活一下 emsdk对应的模块,并配置环境变量,如果没有执行 source ./emsdk_env.sh 配置环境变量的话,在执行下面操作的时候可能会抛出一些变量未定义的错误。

# 在 emsdk 目录下
> mkdir -p emscripten/main binaryen/main
> git clone https://github.com/WebAssembly/binaryen.git binaryen/main
# 国内环境可以使用镜像
# git clone https://gitclone.com/github.com/WebAssembly/binaryen.git binaryen/main
> git clone https://github.com/emscripten-core/emscripten.git emscripten/main
# git clone https://gitclone.com/github.com/emscripten-core/emscripten.git emscripten/main
./emsdk install binaryen-main-64bit emscripten-main-64bit

上面克隆的这两个仓库是 emsdk 的子模块,其中 binaryen 是一个构件工具,而 emscrptenJavaScript 的构件工具,如果我们直接执行 emsdk install 的话 emsdk 会直接去 github 上面克隆这两个仓库供我们使用。但由于网络延迟问题,直接从 github上面克隆仓库的效率其实并不高,因此我们可以先通过镜像将仓库克隆下来,然后在执行 emsdk install这样速度会快的多。

> emsdk activate binaryen-main-64bit emscripten-main-64bitt
> source ./emsdk_env.sh
# 配置环境变量

最后在安装完成后我们可以通过 emsdk 激活这两个模块,注意在激活后需要通过 source ./emsdk_env.sh重新配置下环境变量,否则后续的操作有可能会抛出变量未定义的错误。

上面步骤完成后,我们的环境就基本配置好了,接下来我们可以尝试编写一个c文件,然后用emcc进行编译:

// hello.c
#include
int main(){
	printf("hello world\n");
	return 0;
}

在代码文件 hello.c 编写完成后,执行脚本进行编译:

emcc hello.c -s WASM=1 -o hello.html

在命令执行完成后,当前目录中会多出一些文件,这些分别是编译后的文件产物:
WebAssembly 学习笔记_第3张图片
最后,我们可以通过 emrun指定当前目录来打开一个浏览器查看执行结果:

 emrun --no_browser --port 8082 .

打开浏览器,查看执行结果:
WebAssembly 学习笔记_第4张图片
或者,我们可以通过 node 执行 hello.js,同样能够得到结果:

> node hello.js
hello world

之前看 阮一峰的博客和 WebAssembly 中文中,有部分入门教程和 githubemsdk的操作出现了出入,大概是 emsdk 升级导致操作逻辑发生了改变,需要注意。

参考资料

asm.js 和 Emscripten 入门教程
cmake官网
WebAssembly中文网
introducing_emscripten
WebAssembly官网
Rust
Rust 标准库
编译 Rust 为 WebAssembly
WebAssembly
学习LLVM第1篇:官方入门教程笔记
LLVM:模块化和可重用的编译器和工具链技术的集合
教程简介与词法分析器
WebAssembly
emsdk
emsdk文档
WebAssembly 开发者引导

你可能感兴趣的:(WebAssembly)