惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
Martin Fowler
Martin Fowler
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
B
Blog
U
Unit 42
B
Blog RSS Feed
D
DataBreaches.Net
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
腾讯CDC
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Visual Studio Blog
博客园 - 聂微东
MyScale Blog
MyScale Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
Engineering at Meta
Engineering at Meta

Sanonz

使用 Invox Setup 实现 Electron 安装包界面美化 用 VS Code 编辑器开发 STM32 嵌入式 使用 FontCreator 编辑字体库 | Sanonz 使用 React Context API 和 Hooks 实现全局状态管理和性能优化 使用 Phonegap + Cordova 搭建混合开发平台 利用 Github Actions 自动部署 Hexo 博客 在 WEB 端实现亮/暗主题跟随系统功能 | Sanonz Metalness vs Specular Workflows for PBR Shading 以太坊概念与使用 wep3/infura 实现以太币及合约币交易流程 | Sanonz 实现树莓派(Raspberry Pi)联网发送本机IP到绑定的微信 | Sanonz 使用 Three.js 的 RenderTarget 实现离屏渲染 使用 redux-store-provider 简化 react 开发流程 浏览器 HTTP 并发请求规则探讨 | Sanonz JavaScript Event Loop、Micro Task、Macro Task Let's Encrypt 使用教程,免费的 SSL 证书,让你的网站拥抱 HTTPS Let's Encrypt 使用教程,免费的 SSL 证书,让你的网站拥抱 HTTPS Ubuntu 搭建 php、mysql、nginx 开发环境 | Sanonz WebGL 三维教程 - 绘制矩形和点(二) | Sanonz WebGL 三维教程 - WebGL 介绍(一) Hexo 搭建静态博客与 hexo-theme-concise 主题使用教程 | Sanonz
WebAssembly 从入门到吃鸡 | Sanonz
Sanonz · 2018-01-12 · via Sanonz

WebAssembly 介绍

我们知道 JavaScript 是一门脚本语言,具有动态类型和灵活的表达力,我们知道脚本语言通常要解释运行,这也将要消耗一些性能开销,于是 Google 在 2009 年在 V8 中引入了 JIT(Just in time compiling) 技术,把 JavaScript 运行时的性能推到了顶峰,同年利用 V8 引擎诞生了 Node.js,打开了使用 JavaScript 写后端应用的大门。对于目前写网络应用而言 JavaScript 已经足够用了,加上 Google V8 引擎能帮我们解决掉大部分问题。但是当我们把 JavaScript 应用到诸如 3D 游戏、虚拟现实、增强现实、计算机视觉、图像/视频编辑以及大量的要求原生性能的其他领域的时候,就遇到了性能问题,尤其是移动平台进一步放大了这些性能瓶颈。

而 WebAssembly 的出现就是为了解决这个问题,它是一门低级的类汇编语言,可以运行在现代网络浏览器中的新型代码并且提供新的性能特性和效果。它设计的目的不是为了手写代码,而是为了诸如 C、C++ 和 Rust 等低级源语言提供一个高效的编译目标以便它们能够在网络上运行。对于网络平台而言,这具有巨大的意义——这为客户端 app 提供了一种在网络平台以接近本地速度的方式运行多种语言编写代码的方式;在这之前,客户端 app 是不可能做到的。

WebAssembly 使用

WebAssembly 有二进制 (.wasm) 和文本 (.wast) 两种格式,并且两种格式可以互享转换,在传输和运行时使用二进制格式,而文本格式是为了阅读和开发调试所使用。

以 C 为例,首先把 C 程序编译为 WebAssembly 格式,本地编译可以查看 编译 C/C++ 为 WebAssembly 文章进行相关软件的安装,为了方便可以直接使用这款在线工具进行转换 WasmFiddle

我们先来个简单的,在 main 中返回一个数字,在 add 方法中求和

1
2
3
4
5
6
7
int main() { 
return 42;
}

int add(int a, int b) {
return a + b;
}

转换过后的 .wast 文本格式为,我们可以从这个文本看出分别 export 了 mainadd 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(module
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "main" (func $main))
(export "add" (func $add))
(func $main (; 0 ;) (result i32)
(i32.const 42)
)
(func $add (; 1 ;) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(get_local $1)
(get_local $0)
)
)
)

使用 Fetch 获取模块并初始化调用

1
2
3
4
5
6
7
8
fetch('module.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes))
.then(results => {
console.log(typeof results.instance.exports.main);
console.log(results.instance.exports.main());
console.log(results.instance.exports.add(1, 2));
})

我们可以使用 results.instance.exports.main() 的形式进行调用

使用 XMLHttpRequest 获取模块并初始化调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const request = new XMLHttpRequest();
request.open('GET', 'module.wasm');
request.responseType = 'arraybuffer';

request.onload = function() {
var bytes = request.response;
WebAssembly
.instantiate(bytes)
.then(results => {
results.instance.exports.main();
});
};

request.send();

目前只实现了 JavaScript 语言调用 C 语言,接下来使用 C 调用 JavaScript 方法,声明并在需要的地方调用 alert 方法

1
2
3
4
5
void alert(int a);

int add(int a, int b) {
return alert(a + b);
}

获取实例时传入 importObj 对象,把 env 环境变量注入进来

1
2
3
4
5
6
7
8
9
10
11
const importObj = {
env: {
alert: window.alert
}
};
fetch('module.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, importObj))
.then(results => {
console.log(results.instance.exports.add(1, 2));
})

至此相互调用演示完成,我们可以畅想下以后 WebAssembly 普及的话,到时我们用的 React、Vue、Angular 可能就是用 C/C++ 或者其他底层语言写的。