初探 WebAssembly

什么是 WebAssembly?

  • 一种新型的代码,可以运行在 Web 浏览器,提供一些新特性并主要专注于高性能
  • 主要不是用于写,而是 C/C++、C#、Rust 等语言编译的目标,所以你即使不知道如何编写 WebAssembly 代码也能利用它的优势
  • 其他语言编写的代码也能以近似于原生速度运行,客户端 App 也能在 Web 上运行
  • 在浏览器或 Node.js 中可以导入 WebAssembly 模块,JS 框架能够使用 WebAssembly 来获得巨大的性能优势和新的特性的同时在功能上易于使用

优势

  • 快、便利:通过利用一些通用的硬件能力,能够跨平台以近乎于原生的速度执行
  • 可读、可调试:WebAssembly 是一种低层次的汇编语言,但是它也有一种人类可读的文本格式,使得人们可编写代码、查看代码、可调试代码。
  • 确保安全:WebAssembly 明确运行在安全、沙箱的执行环境,类似其他 Web 的代码,它会强制开启同源和一些权限策略。
  • 不破坏现有的 Web: WebAssembly 被设计与其他 Web 技术兼容运行,并且保持向后兼容性。

编码平台 WebAssembly 给 Web 平台添加了两块内容:一种二进制格式代码,以及一系列可用于加载和执行二进制代码的 API。 WebAssembly 目前处于一个萌芽的节点,之后肯定会涌现出很多工具,而目前有四个主要的入口:

  • 在汇编层面直接编写和生成 WebAssembly 代码(.wat -> .wasm)
  • 使用 EMScripten 来移植 C/C++ 应用
  • 编写 Rust 应用,然后将 WebAssembly 作为它的输出 wasm-pack
  • 使用 AssemblyScript,它是一门类似 TypeScript 的语言,能够编译成 WebAssembly 二进制

Js 中使用 .wasm 文件

浏览器不能直接用.wasm 格式的文件中的函数和数据,需要拿 js 先写一些胶水代码。(通常能将高级语言编译为.wasm的框架都有生成胶水代码的能力)

使用逻辑:.wasm文件 -> 胶水代码 -> 业务代码

C & Cpp

安装

  1. git clone https://github.com/juj/emsdk.git
  2. win 和 mac 在略有不同
    1. win:emsdk install --global latest
    2. mac:./emsdk install --global latest
  3. win 环境下每次重启终端都要执行一次,windows电脑中只能在cmd、powershell中使用,在git bash无效
    1. emsdk activate latest
    2. ./emsdk activate latest
  4. 如果没有这个脚本,下一步会提醒手动设置全局变量
    1. emsdk_env.bat
    2. source ./emsdk_env.sh
  5. emcc -v :如果有log,说明安装成功

使用

c 复制代码
#include <stdio.h>
#include <emscripten/emscripten.h> // 需要引入这个包来导出函数

EMSCRIPTEN_KEEPALIVE
int fib(int n) {
  if (n < 2) {
    return n;
  } else {
    return fib(n - 1) + fib(n - 2);
  }
}

EMSCRIPTEN_KEEPALIVE
int main(int argc, char ** argv) {
  printf("fib(40) = %d\n", fib(40));
}

简单应用的话在cmd emcc <fileNmae>.c 用于生成 .wasm 文件,同时也会生成一个对应的 .js,即胶水代码,可以通过这个文件直接使用 .wasm中封装好的方法。

emcc fib.c -o fib.wasm --no-entry -O3:自己写胶水代码的话可以直接用这个,main函数运行时的依赖参数就可以不用传入。其中 -O3 最好加上(或者更高程度的优化指令),不然跑起来可能比 js 的代码还慢

stackoverflow.com/questions/5...

更多指令: Emscripten 编译器(emcc) 命令总结

Rust

安装

  1. 安装 rust,上官网,cargo也会一起装好
  2. cargo install wasm-pack:在window平台它是依赖 visual studio 中的一些 sdk 的,所以要先装一下 vs,不然执行这条命令的时候会报错
  3. cargo new <folderName>

使用

  1. 配置 Cargo.toml,下面是编译为 .wasm 最基本的配置
toml 复制代码
[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
  1. demo文件
rust 复制代码
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fib(n: i32) -> i32 {
    if n <= 1 {
        return n;
    }
    fib(n - 1) + fib(n - 2)
}
  1. wasm-pack build --target web:生成的 .wasm 文件和胶水代码会在 pkg 目录下

AssmeblyScript

安装

  1. npm install -D assemblyscript
  2. npx asinit .:生成脚手架,然后跟着脚手架走就行

使用

AssemblyScript 可以理解为 Typescript 的子集,数据类型很少类型 | AssemblyScript 中文网 写起来就是ts,编译之后为wasm,不过一年了才从 0.26 -> 0.27,所以可以理解为半死不活的状态,不推荐使用。

typescript 复制代码
export function fib(num: i32): i32 {
  if (num < 2) {
    return num;
  } else {
    return fib(num - 1) + fib(num - 2);
  }
}

对比

用简单的斐波那契数列算法来做对比的话

踩坑记录

common:

  1. 引用文件时需要本地起一个 server

c2wasm:

  1. 要先装python环境,不然安装不会有反应
  2. mac环境中装了python仍然报错
    1. 解决方案:在emsdk.py中添加如下两行代码issue with emsdk on mac
python 复制代码
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
  1. -O3 这类优化在发包的时候一定要加上,不然跑起来可能比js还慢

rust2wasm:

  1. 要先装visul studio,不然安装 wasm-pack 的时候会报错没有 link.exe。也可以不安装vs,有兴趣的可以自己查查看
  2. rust的胶水代码可读性比较强,可以作为参考

参考资料

tigercosmos.xyz/post/2020/0...

相关推荐
w_y_fan13 小时前
Flutter 滚动组件总结
前端·flutter
wuli金居哇13 小时前
我用 Turborepo 搭了个 Monorepo 脚手架,开发体验直接起飞!
前端
Asort13 小时前
JavaScript 从零开始(五):运算符和表达式——从零开始掌握算术、比较与逻辑运算
前端·javascript
一枚前端小能手13 小时前
🚀 缓存用错了网站更慢?前端缓存策略的5个致命误区
前端·javascript
艾小码13 小时前
为什么你的页面会闪烁?useLayoutEffect和useEffect的区别藏在这里!
前端·javascript·react.js
艾小码13 小时前
告别Vue混入的坑!Composition API让我效率翻倍的3个秘密
前端·javascript·vue.js
南雨北斗13 小时前
VS Code 中手动和直接运行TS代码
前端
小高00713 小时前
🔍说说对React的理解?有哪些特性?
前端·javascript·react.js
烛阴13 小时前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
Samsong13 小时前
JavaScript逆向之反制无限debugger陷阱
前端·javascript