В 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): удалены префиксы поставщиков и обновлены фрагменты кода.