W Chrome 13 wprowadzono wysyłanie ArrayBuffer
do/z Web Worker za pomocą algorytmu o nazwie strukturalne klonowanie. Dzięki temu interfejs API postMessage()
może przyjmować wiadomości, które nie są tylko ciągami znaków, ale też złożone typy, takie jak File
, Blob
, ArrayBuffer
i obiekty JSON. Strukturalne klonowanie jest obsługiwane także w nowszych wersjach Firefoksa.
Szybciej znaczy lepiej
Strukturalne klonowanie jest świetne, ale nadal jest to operacja kopiowania. Przekazywanie danych o rozmiarze 32 MB ArrayBuffer
do instancji roboczej może zająć setki milisekund.
Nowe wersje przeglądarek zawierają ogromną poprawę wydajności przekazywania wiadomości, zwaną obiektmi przenośnymi.
W przypadku obiektów możliwych do przeniesienia dane są przenoszone z jednego kontekstu do drugiego. Jest to metoda bez kopiowania, która znacznie poprawia wydajność wysyłania danych do Workera. Jeśli pochodzisz ze świata C/C++, możesz traktować to jak przekazywanie przez referencję. Jednak w odróżnieniu od przekazywania przez odniesienie „wersja” z kontekstu wywołania nie jest już dostępna po przeniesieniu do nowego kontekstu. Na przykład podczas przenoszenia ArrayBuffer
z aplikacji głównej do Workera oryginalny obiekt ArrayBuffer
jest czyszczony i nie można go już używać. Jego zawartość jest (dosłownie) przenoszona do kontekstu Worker.
Aby grać z przenośnymi, dostępna jest nowa wersja postMessage()
, która obsługuje przenośne obiekty:
worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);
W przypadku pracownika pierwszym argumentem jest wiadomość ArrayBuffer
. Drugi argument to lista elementów, które mają zostać przeniesione. W tym przykładzie na liście do przeniesienia musisz podać wartość arrayBuffer
.
Demonstracja porównawcza
Aby zobaczyć wzrost skuteczności, jaki dają elementy przenośne, przygotowałem prezentację demonstracyjną.
Demo wysyła ArrayBuffer
o rozmiarze 32 MB do instancji roboczej i z powrotem, korzystając z funkcji postMessage()
. Jeśli Twoja przeglądarka nie obsługuje przenośnych, próbka użyje klonowania ustrukturyzowanego. Średnia z 5 wykonań w różnych przeglądarkach:
Na komputerze MacBook Pro/10.6.8/2.53 GHz/Intel Core 2 Duo najszybszy był FF z wykorzystaniem strukturalnego klonowania. Wysłanie 32 MB danych (ArrayBuffer
) do workera i przesłanie ich z powrotem do wątku głównego (RRT – czas błądzenia) zajęło średnio 302 ms. W przypadku transferów porównywalnych czas wykonania tego samego testu wynosił 6, 6 ms. To ogromny wzrost wydajności.
Dzięki takim prędkościom można bezproblemowo przekazywać duże tekstury lub siatki WebGL między Workerem a aplikacją główną.
Wykrywanie funkcji
Wykrywanie tej funkcji jest nieco trudne. Zalecamy wysłanie pracownikowi niewielkiej ArrayBuffer
. Jeśli bufor zostanie przeniesiony, a nie skopiowany, jego wartość .byteLength
będzie wynosić 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.
}
Obsługa: obecnie Chrome w wersji 17 lub nowszej, Firefox, Opera, Safari i IE w wersji 10 lub nowszej.
Aktualizacja (13.12.2011): fragment kodu, który wyświetla podpis webkitPostMessage()
, jest inny w przypadku okna i elementu worker.
Aktualizacja (3 listopada 2016 r.): usunięto prefiksy dostawców i zaktualizowano fragmenty kodu