Переносимые объекты — молниеносно

В Chrome 13 появилась возможность отправки ArrayBuffer в/из Web Worker с использованием алгоритма, называемого структурированным клонированием . Это позволило API postMessage() принимать сообщения, которые представляли собой не просто строки, а сложные типы, такие как объекты File , Blob , ArrayBuffer и JSON. Структурированное клонирование также поддерживается в более поздних версиях Firefox.

Быстрее лучше

Структурированное клонирование — это здорово, но это все равно операция копирования. Накладные расходы на передачу ArrayBuffer размером 32 МБ в Worker могут составлять сотни миллисекунд. Новые версии браузеров содержат значительное улучшение производительности при передаче сообщений, называемое Transferable Objects .

С помощью передаваемых объектов данные передаются из одного контекста в другой. Это нулевое копирование, что значительно повышает производительность отправки данных работнику. Если вы из мира C/C++, думайте об этом как о передаче по ссылке. Однако, в отличие от передачи по ссылке, «версия» из контекста вызова больше не доступна после передачи в новый контекст. Например, при переносе ArrayBuffer из основного приложения в Worker исходный ArrayBuffer очищается и больше не пригоден для использования. Его содержимое (в буквальном смысле слова) переносится в контекст Worker.

Чтобы поиграть с передаваемыми объектами, существует новая версия postMessage() , которая поддерживает передаваемые объекты:

worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);

В рабочем случае первым аргументом является сообщение ArrayBuffer . Второй аргумент — это список элементов, которые следует передать. В этом примере вы должны указать arrayBuffer в передаваемом списке.

Тестовая демо-версия

Чтобы увидеть прирост производительности передаваемых объектов, я собрал демо-версию .

Демонстрационная версия отправляет ArrayBuffer размером 32 МБ рабочему процессу и обратно с помощью postMessage() . Если ваш браузер не поддерживает передаваемые данные, образец возвращается к структурированному клонированию. Усреднив 5 запусков в разных браузерах, вот что я получил:

Сравнительная таблица структурированного клонирования и передаваемых объектов

На MacBook Pro/10,6,8/2,53 ГГц/Intel Core 2 Duo FF оказался самым быстрым при использовании структурированного клонирования. В среднем потребовалось 302 мс, чтобы отправить 32-мегабайтный ArrayBuffer рабочему процессу и отправить его обратно в основной поток (RRT — время прохождения туда и обратно). По сравнению с передаваемыми данными, тот же тест занял 6,6 мс. Это огромный прирост производительности!

Наличие таких скоростей позволяет беспрепятственно передавать массивные текстуры/сетки WebGL между Worker и основным приложением.

Обнаружение функций

Обнаружение функций в этом случае немного сложнее. Я рекомендую отправить вашему работнику небольшой ArrayBuffer . Если буфер передан, а не скопирован, его .byteLength станет равным 0:

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
if (ab.byteLength) {
    alert('Transferables are not supported in your browser!');
} else {
    // Transferables are supported.
}

Поддержка: на данный момент Chrome 17+, Firefox, Opera, Safari и IE10+.

Обновлено (13 декабря 2011 г.): Фрагмент кода для отображения подписи webkitPostMessage() отличается для окна и работника. Обновлено (03.11.2016): удалены префиксы поставщиков и обновлены фрагменты кода.