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

相关推荐
weixin_382395231 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__1 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.2 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~3 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华4 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子6 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅6 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni7 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学8 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端