Быстрее ли нарисовать серию изображений на холсте с помощью WebAssembly? - PullRequest
1 голос
/ 23 апреля 2020

Я хочу спросить, быстрее ли и эффективнее ли память рисовать серию изображений на холсте с помощью WebAssembly / WASM?

Я спрашиваю об этом, так как я тестировал рисование серии изображений (анимации) как в основном пользовательском интерфейсе, так и с веб-работниками. Для нескольких холстов ( 1-5 холстов ) производительность невыносима, однако для большего количества холстов (, например, 20-25 ) сценарий немного отличается, рендеринг становится замедленным.

Вот код в основном пользовательском интерфейсе:

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

Вот мой веб-работник:

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();
}

Это работает Хорошо, что он может отображать изображения в браузере от веб-работника, но, как уже упоминалось, при 1-5 полотнах он все еще плавный, но с большим количеством полотен рендеринг в браузере становится очень медленным.

Итак, я хочу спросить быстрее ли рисовать серии изображений на холсте с помощью WebAssembly ? Или не будет никакого теоретического прироста производительности по сравнению с тем, как это делается сейчас с подходом веб-работника?

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

WebAssembly может быть быстрее для сложных вычислений в байтовом массиве, но основной поток JavaScript UI все равно будет выполнять рендеринг от ArrayBuffer до canvas. Пока вы «повторно используете» ArrayBuffer экземпляры, передавая объекты с интерфейсом Transferable между основным потоком пользовательского интерфейса и WebWorker, вы сможете легко и быстро обновлять холст.

При рендеринге обновлений для нескольких объектов canvas рассмотрите возможность их пакетирования в функции requestAnimationFrame(), чтобы минимизировать перекрашивание пикселей в браузере. Это должно значительно улучшить производительность кадровой сети браузера.

1 голос
/ 23 апреля 2020

Итак, я хочу спросить, быстрее ли рисовать серии изображений на Canvas с WebAssembly?

WebAssembly может быть быстрее, чем JavaScript, но это не всегда. Это очень сильно зависит от типа вычислений, которые вы выполняете. Вероятно, самая сильная сторона WebAssembly в том, что производительность предсказуема и постоянна. Этот пост в блоге дает, пожалуй, самые информативные реальные результаты производительности:

https://hacks.mozilla.org/2018/01/oxidizing-source-maps-with-rust-and-webassembly/

Или теоретический прирост производительности по сравнению с этим не будет теперь с подходом веб-работника?

Эти два метода никоим образом не являются взаимоисключающими! Вы можете запустить WebAssembly в Web Worker и использовать общую память (аналогично SharedArrayBuffer), чтобы обеспечить многопоточный доступ к данным изображения. Это сообщение в блоге дает пример того, как WebAssembly может использоваться для вычисления алгоритма в нескольких рабочих потоках:

https://blog.scottlogic.com/2019/07/15/multithreaded-webassembly.html

В ответ на ваши особенности, видео декодеры (которые обычно пишутся на C ++) являются очень хорошим кандидатом для WebAssembly. Я бы предложил создать несколько веб-работников, каждый с декодером на основе WebAssembly.

...