原文链接: js worker 中wasm的性能测试
上一篇: 基于C的WebAssembly 和 Web Worker
下一篇: js 驼峰和下划线命名互转
worker中wasm加载时间几乎不计, 也可能是代码比较简单, 不过这个加载时间应该比不上执行时间的零头是肯定的
在worker中js代码执行效率和wasm的执行效率几乎一样, 前几年worker中的执行效率还只有七成左右
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script type="module">
function fibJs(n) {
return n < 2 ? n : fibJs(n - 1) + fibJs(n - 2);
}
async function main() {
const url = "http://172.24.162.13:5000/cpp2/math.wasm";
const buffer = await fetch(url) // 加载文件
.then((res) => res.arrayBuffer()); // 转成 ArrayBuffer
const wasm = await WebAssembly.instantiate(buffer);
const fibWasm = wasm.instance.exports.fib;
const worker = new Worker("./fib-worker.js");
function workerPromise(n, type = "js") {
return new Promise((resolve, reject) => {
const wasmBuffer = buffer.slice(0, buffer.byteLength);
worker.postMessage({ n, wasmBuffer, type });
const handle = ({ data }) => {
// console.log("resolve", data);
resolve(data);
worker.removeEventListener("message", handle);
};
worker.addEventListener("message", handle);
});
}
async function testJs(n) {
const st = +new Date();
const result = fibJs(n);
const ed = +new Date();
const time = ed - st;
console.log("testJs", { result, time });
return { time };
}
async function testWasm(n) {
const st = +new Date();
const result = fibWasm(n);
const ed = +new Date();
const time = ed - st;
console.log("testWasm", { result, time });
return { time };
}
async function testWorkerJs(n, type = "js") {
const st = +new Date();
const data = await workerPromise(n, type);
const { result, workerTime, wasmTime = 0 } = data;
const ed = +new Date();
const time = ed - st;
console.log(type === "js" ? "testWorkerJs" : "testWorkerWasm", {
result,
time,
workerTime,
wasmTime,
});
return { time, workerTime, wasmTime };
}
async function testWorkerWasm(n) {
return await testWorkerJs(n, "wasm");
}
const click = async () => {
for (let i = 0; i < 40; i++) {
const { time: timeJs } = await testJs(i);
const { time: timeWasm } = await testWasm(i);
const { time: timeWorkerJs } = await testWorkerJs(i);
const { time: timeWorkerWasm } = await testWorkerWasm(i);
console.log("time compare:", i, {
timeJs,
timeWasm,
timeWorkerJs,
timeWorkerWasm,
});
}
};
document.addEventListener("click", click);
}
main();
</script>
</html>
fib-worker.js
function workerFibJs(n) {
return n < 2 ? n : workerFibJs(n - 1) + workerFibJs(n - 2);
}
self.onmessage = async ({ data }) => {
// console.log("self data", data);
if (data.type === "js") {
const st = +new Date();
const result = workerFibJs(data.n);
const ed = +new Date();
self.postMessage({ result, workerTime: ed - st, wasmTime: -1 });
} else {
const { n, wasmBuffer } = data;
const st1 = +new Date();
const wasm = await WebAssembly.instantiate(wasmBuffer);
// console.log("wasm", wasm);
const st2 = +new Date();
const fib = wasm.instance.exports.fib;
const result = fib(n);
const ed = +new Date();
self.postMessage({ result, workerTime: ed - st1, wasmTime: ed - st2 });
}
};