使用 WebAssembly 在 Canvas 上绘制一系列图像是否更快?

Que*_*aut 7 html javascript html5-canvas emscripten webassembly

我想问使用 WebAssembly/WASM 将一系列图像绘制到画布中是否更快、更节省内存?

我之所以这么问,是因为我已经测试过在主 UI 和网络工作人员中绘制一系列图像(动画)。对于少数画布(1-5 个画布),性能是可以忍受的,但是对于更多画布(如 20-25),场景会有点不同,渲染变得慢动作。

这是主 UI 中的代码:

const videoDecoder = new Worker("videoDecoder.js");
const canvas = document.querySelector("#canvas");
const offscreen = canvas.transferControlToOffscreen();
videoDecoder.postMessage({ action: 'init', canvas: offscreen }, [offscreen] );
Run Code Online (Sandbox Code Playgroud)

这是我的网络工作者:

onmessage = async function (e) {
    const blob = e.data;
    blob.arrayBuffer().then(arrayBuffer => {
        const uint8Array = new Uint8Array(arrayBuffer);
        for(;;;) {
           const offsetIdx = ...;
           const endIdx = ...;
           const jpegArray = uint8Array.slice(offsetIdx, endIdx);
           const blob = new Blob([jpegArray], {type: "image/jpeg"});
           drawImage(blob);
        }
    }
}

async function drawImage(blob) {
    const bmp = await createImageBitmap(blob);
    context.drawImage(bmp, 0, 0);
    bmp.close();
}
Run Code Online (Sandbox Code Playgroud)

这工作得很好,它可以将图像从 Web Worker 渲染到浏览器,但正如前面提到的,在 1-5 个画布上,它仍然很流畅,但画布越多,浏览器中的渲染就会变得非常慢。

所以我想问用WebAssembly在Canvas上绘制一系列图像是否更快?或者与现在使用 Web Worker 方法相比,理论上不会有任何性能提升?

Ant*_*ris 3

WebAssembly 对于字节数组的复杂计算可能更快,但主 JavaScript UI 线程仍将渲染ArrayBufferto canvas。只要您ArrayBuffer通过在Transferable主 UI 线程和 WebWorker 之间的接口传递对象来“重用”实例,您就应该能够轻松高效地更新画布。

当渲染多个canvas对象的更新时,请考虑在函数中对它们进行批处理requestAnimationFrame(),以最大程度地减少浏览器中像素的重新绘制。这应该会显着提高浏览器帧速率性能。

  • 这完全取决于发生的计算量。我始终建议对所有性能比较进行 A/B 测试和测量。理论上,对于更复杂的算法,WASM 应该更快。您的慢动作可能是由于主 UI 线程上的多次重绘造成的 (2认同)