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

相关推荐
再学一点就睡6 小时前
前端网络实战手册:15个高频工作场景全解析
前端·网络协议
C_心欲无痕6 小时前
有限状态机在前端中的应用
前端·状态模式
C_心欲无痕6 小时前
前端基于 IntersectionObserver 更流畅的懒加载实现
前端
candyTong7 小时前
深入解析:AI 智能体(Agent)是如何解决问题的?
前端·agent·ai编程
柳杉7 小时前
建议收藏 | 2026年AI工具封神榜:从Sora到混元3D,生产力彻底爆发
前端·人工智能·后端
weixin_462446237 小时前
使用 Puppeteer 设置 Cookies 并实现自动化分页操作:前端实战教程
运维·前端·自动化
CheungChunChiu7 小时前
Linux 内核动态打印机制详解
android·linux·服务器·前端·ubuntu
Irene19918 小时前
Vue 官方推荐:kebab-case(短横线命名法)
javascript·vue.js
GIS之路8 小时前
GDAL 创建矢量图层的两种方式
前端
2501_948195349 小时前
RN for OpenHarmony英雄联盟助手App实战:符文配置实现
javascript·react native·react.js