初探 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...

相关推荐
小兵张健7 小时前
价值1000的 AI 工作流:Codex 通用前端协作模式
前端·aigc·ai编程
sunny_7 小时前
面试踩大坑!同一段 Node.js 代码,CJS 和 ESM 的执行顺序居然是反的?!99% 的人都答错了
前端·面试·node.js
拉不动的猪7 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
ayqy贾杰9 小时前
Agent First Engineering
前端·vue.js·面试
IT_陈寒9 小时前
SpringBoot实战:5个让你的API性能翻倍的隐藏技巧
前端·人工智能·后端
iceiceiceice10 小时前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
大金乄10 小时前
封装一个vue2的elementUI 表格组件(包含表格编辑以及多级表头)
前端·javascript
葡萄城技术团队10 小时前
【性能优化篇】面对万行数据也不卡顿?揭秘协同服务器的“片段机制 (Fragments)”
前端
程序员阿峰11 小时前
2026前端必备:TensorFlow.js,浏览器里的AI引擎,不写Python也能玩转智能
前端
Jans11 小时前
Shipfe — Rust 写的前端静态部署工具:一条命令上线 + 零停机 + 可回滚 + 自动清理
前端