TechTalk

WebAssembly是什么

字数统计: 1.1k阅读时长: 4 min
2022/05/09

前言

近期趁着5.1期间,学习了一些新的内容,陆续的做一些总结和输出,浏览器中的Python算是这几天学习的一个小节点吧。这里先总结下WebAssembly。
由于主流的浏览器(Chrome、Safari、Firefox, 微软Edge)开始支持WebAssembly,使得其他语言(C,C++,Python,…)运行在浏览器中称为一种可能。
2017年11月,以上四个浏览器都开始实验性的支持WebAssembly[5][6]。WebAssembly 于 2019 年 12 月 5 日成为万维网联盟(W3C)的推荐,与 HTML,CSS 和 JavaScript 一起,成为 Web 的第四种语言。

JS在移动设备上,会比原生应用(Android,IOS)慢很多,于是W3C社区就想创造了WebAssembly的技术作为JS的补充。

WebAssembly

什么是WebAssembly,顾名思义,是可以被浏览器执行的Web级别的汇编级别的字节码或者说是格式标准,可以理解为等同于Intel/AMD CPU执行的RISC X86指令集。
WebAssembly也叫做WASM(下文均适用WASM),相关的规范在GitHub的这个页面 。WASM定义了一个可移植的,具有大小和加载高效的二进制格式来作为编译标准。
WASM的标准至2017年发布以来,一直进行改进和演进。
WASM几个相关工具:

  • AssemblyScript, 支持直接将TypeScript编译成WebAssembly。这对于很多前端同学来说,入门的门槛还是很低的。
  • Emscripten,可以说是WebAssembly的灵魂工具不为过,上面说了很多编译,这个就是那个编译器。将其他的高级语言,编译成WebAssembly。
  • WABT,是个将WebAssembly在字节码和文本格式相互转换的一个工具,方便开发者去理解这个wasm到底是在做什么事。

WASM如何运行

通常情况下,例如使用C开发的程序,如果需要使用WASM方式运行在浏览器中,那么一般会经过如下步骤:

  1. 使用LLVM以及Emscripten构建开发环境。
  2. 使用上一步的emcc程序将.c源码编译成wasm字节码文件。
  3. 将上一步生成的wasm字节码文件引入到相应的html页面中,浏览器加载该wasm文件并执行。
  4. 在运行期,wasm运行在浏览器的WASM VM中。

WASM具有文本格式的表达文件WAST,例如hello-world.wast内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(module
;; Imports from JavaScript namespace
(import "console" "log" (func $log (param i32 i32))) ;; Import log function
(import "js" "mem" (memory 1)) ;; Import 1 page of memory (54kb)

;; Data section of our module
(data (i32.const 0) "Hello World from WebAssembly!")

;; Function declaration: Exported as helloWorld(), no arguments
(func (export "helloWorld")
i32.const 0 ;; pass offset 0 to log
i32.const 29 ;; pass length 29 to log (strlen of sample text)
call $log
)
)

下图中是一段代码的WAST以及WASM格式的对比:
wast-wasm

下面的html文件的例子将wasm文件加载到html页面中,然后执行该wasm中c的一个导出函数c_hello

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!doctype html> 
<html>
<head>
<meta charset="utf-8">
<title>WebAssembly Add Function</title>
<style>
div {
font-size : 30px; text-align : center; color:orange;
}
</style>
</head>
<body>
<div id="textcontent"></div>
<script>
fetch("firstprog.wasm")
.then(bytes => bytes.arrayBuffer())
.then(mod => WebAssembly.compile(mod))
.then(module => {return new WebAssembly.Instance(module)})
.then(instance => {
console.log(instance);
let buffer = new Uint8Array(instance.exports.memory.buffer);
let test = instance.exports.c_hello();
let mytext = "";
for (let i=test; buffer[i]; i++) {
mytext += String.fromCharCode(buffer[i]);
}
console.log(mytext); document.getElementById("textcontent").innerHTML = mytext;
});
</script>
</body>
</html>

这样的一个html页面的展示效果如下:
html-wasm

WASM与Javascript关系

WebAssembly是被设计成JavaScript的一个完善、补充,而不是一个替代品。WebAssembly将很多编程语言带到了Web中。但是JavaScript因其不可思议的能力,仍然将保留现有的地位。
长期来讲,WASM的野心可能是重构前端生态,JS可能只其中的一个过渡,目前的情况看起来,WASM的性能还不太行。WASM提供了一种更加接近CPU、GPU乃至于AI芯片的方法,在终端手机上能够更加便捷的提高性能。

WASM如何操作DOM

WASM目前还不能直接访问DOM,WASM只能通过javascript来完成,WASM后续有计划会直接调用Web API。

参考

CATALOG
  1. 1. 前言
  2. 2. WebAssembly
    1. 2.1. WASM如何运行
    2. 2.2. WASM与Javascript关系
    3. 2.3. WASM如何操作DOM
  3. 3. 参考