纯C的比c++好编译和使用, 没有胶水的js, 以及简单的直接用exports就能拿到函数
这个是c的worker共享内存, 但是感觉效果也不是很好... wasm的多线程, 目前还没有表现比较好的例子
在浏览器或者node中直接运行
WebAssembly.compile(
new Uint8Array(
`
00 61 73 6d 01 00 00 00 01 0c 02 60 02 7f 7f 01
7f 60 01 7f 01 7f 03 03 02 00 01 07 10 02 03 61
64 64 00 00 06 73 71 75 61 72 65 00 01 0a 13 02
08 00 20 00 20 01 6a 0f 0b 08 00 20 00 20 00 6c
0f 0b`
.trim()
.split(/[\s\r\n]+/g)
.map((str) => parseInt(str, 16))
)
).then((module) => {
const instance = new WebAssembly.Instance(module);
const { add, square } = instance.exports;
console.log("2 + 4 =", add(2, 4));
console.log("3^2 =", square(3));
console.log("(2 + 5)^2 =", square(add(2 + 5)));
});
math.c
int add(int x, int y)
{
return x + y;
}
int square(int x)
{
return x * x;
}
int fib(int n)
{
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
/*
emcc math.c -Os -s WASM=1 -s SIDE_MODULE=1 -o math.wasm
*/
node的使用
const url = "./cpp/math.wasm";
const fs = require("fs");
const buffer = fs.readFileSync(url);
WebAssembly.instantiate(buffer).then((wasm) => {
const instance = wasm.instance;
const add = instance.exports.add;
const square = instance.exports.square;
console.log("add", add(1, 2));
console.log("square", square(2));
});
web的使用, 和node的使用一样, 只是使用fetch来代替fs
Documentconst url = "http://172.24.162.13:44593/cpp/math.wasm";
function loadWebAssembly(path) {
return fetch(path) // 加载文件
.then((res) => res.arrayBuffer()) // 转成 ArrayBuffer
.then(WebAssembly.instantiate) // 编译 + 实例化
.then((mod) => mod.instance); // 提取生成都模块
}
loadWebAssembly(url).then((instance) => {
const add = instance.exports.add;
const square = instance.exports.square;
console.log("add", add(1, 2));
console.log("square", square(2));
});
最简单的使用, 40项fib
每个计算用一个worker, 基本没啥提速的....
会有大量请求
Documentconst size = 40;
function workerPromise(n) {
const worker = new Worker("./fib-worker.js");
return new Promise((resolve) => {
worker.postMessage(n);
worker.onmessage = ({ data }) => {
// console.log(n, data);
resolve(data);
};
});
}
async function worker() {
const list = Array(size)
.fill()
.map((_, k) => k);
const st = +new Date();
const promiseList = list.map(workerPromise);
const resList = await Promise.all(promiseList);
const ed = +new Date();
console.log("wasm time:", ed - st);
console.log(list, resList);
}
worker();
async function test() {
const st = +new Date();
const url = "http://172.24.162.13:44593/cpp/math.wasm";
const fib = await fetch(url) // 加载文件
.then((res) => res.arrayBuffer()) // 转成 ArrayBuffer
.then(WebAssembly.instantiate) // 编译 + 实例化
.then((mod) => mod.instance.exports.fib);
const list = [];
for (let i = 0; i < size; i++) {
list.push(fib(i));
}
const ed = +new Date();
console.log("test time:", ed - st, list);
}
test();
const url = "http://172.24.162.13:44593/cpp/math.wasm";
function loadWebAssembly(path) {
return fetch(path) // 加载文件
.then((res) => res.arrayBuffer()) // 转成 ArrayBuffer
.then(WebAssembly.instantiate) // 编译 + 实例化
.then((mod) => mod.instance); // 提取生成都模块
}
self.onmessage = ({ data }) => {
// console.log("worker", data);
loadWebAssembly(url).then((instance) => {
const fib = instance.exports.fib;
self.postMessage(fib(data));
});
};
优化版, 一个worker, 感觉也没啥提升的...
虽然网络请求明显少了....
Documentasync function main() {
const url = "http://172.24.162.13:44593/cpp/math.wasm";
const buffer = await fetch(url) // 加载文件
.then((res) => res.arrayBuffer()); // 转成 ArrayBuffer
console.log("buffer", buffer);
const size = 40;
const begin = 0;
const worker = new Worker("./fib-worker4.js");
function workerPromise(n) {
return new Promise((resolve, reject) => {
const wasmBuffer = buffer.slice(0, buffer.byteLength);
worker.postMessage({ n, wasmBuffer });
const handle = ({ data }) => {
const { resN, fib } = data;
// console.log("onmessage", n, resN, fib);
if (resN === n) {
// console.log("resolve", n, resN, fib);
resolve(fib);
worker.removeEventListener("message", handle);
}
};
worker.addEventListener("message", handle);
});
}
async function workerTest() {
console.log("workerTest");
const st = +new Date();
const list = [];
for (let i = begin; i < size; i++) {
list.push(i);
}
const resList = await Promise.all(list.map(workerPromise));
const ed = +new Date();
console.log("wasm time:", ed - st);
console.log("res", resList);
}
workerTest();
async function test() {
const st = +new Date();
const wasm = await WebAssembly.instantiate(buffer);
const fib = wasm.instance.exports.fib; // 编译 + 实例化
const list = [];
for (let i = begin; i < size; i++) {
list.push(fib(i));
}
const ed = +new Date();
console.log("test time:", ed - st, list);
}
test();
}
main();
self.onmessage = async (msg) => {
// console.log("msg", msg);
const { n, wasmBuffer } = msg.data;
// console.log("worker wasmBuffer", n, wasmBuffer);
const wasm = await WebAssembly.instantiate(wasmBuffer);
const fib = wasm.instance.exports.fib;
const res = fib(n);
// console.log("worker res", n, res);
self.postMessage({ resN: n, fib: res });
};