W Chrome 13 wprowadzono wysyłanie żądań ArrayBuffer
do i z instancji roboczej Web Worker za pomocą algorytmu o nazwie klonowanie ustrukturyzowane. Dzięki temu interfejs API postMessage()
akceptował wiadomości, które nie były tylko ciągami tekstowymi, ale typy złożone, takie jak File
, Blob
, ArrayBuffer
i obiekty JSON. Klonowanie uporządkowane jest też obsługiwane w nowszych wersjach Firefoksa.
Szybciej znaczy lepiej
Klonowanie uporządkowane to świetna sprawa, ale nadal jest to operacja kopiowania. Narzut danych ArrayBuffer
o rozmiarze 32 MB do instancji roboczej może wynosić setki milisekund.
Nowe wersje przeglądarek zapewniają znaczący wzrost wydajności przekazywania wiadomości, zwany obiektami z możliwością przenoszenia.
W przypadku obiektów przenoszonych dane są przenoszone z jednego kontekstu do drugiego. To zero-kopia, która znacznie poprawia wydajność wysyłania danych do instancji roboczej. Jeśli pochodzisz ze świata C/C++, możesz myśleć o tym jako o przekazywanym w ten sposób pliku referencyjnym. Jednak w przeciwieństwie do przekazywania dalej, „wersja” z kontekstu wywołania nie jest już dostępna po przeniesieniu do nowego kontekstu. Na przykład podczas przenoszenia elementu ArrayBuffer
z aplikacji głównej do instancji roboczej pierwotny plik ArrayBuffer
zostaje wyczyszczony i nie można go już używać. Jego zawartość jest przenoszona (dosłownie) do kontekstu instancji roboczej.
Jeśli chcesz grać z materiałami przenoszonymi, jest dostępna nowa wersja postMessage()
, która obsługuje te obiekty:
worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);
W przypadku instancji roboczych pierwszy argument to komunikat ArrayBuffer
. Drugi argument to lista elementów do przesłania. W tym przykładzie podasz arrayBuffer
na liście możliwych do przeniesienia.
Demonstracja
Przygotowałem prezentację, aby sprawdzić wzrost wydajności urządzeń przenoszonych.
Wersja demonstracyjna wysyła ArrayBuffer
o wielkości 32 MB do instancji roboczej i z powrotem za pomocą postMessage()
. Jeśli Twoja przeglądarka nie obsługuje elementów z możliwością przeniesienia, w przykładzie pojawia się ustrukturyzowane klonowanie. Średnio 5 działań w różnych przeglądarkach wygląda tak:
Na komputerach MacBook Pro/10.6.8/2, 53 GHz/Intel Core 2 Duo najszybszym sposobem na wykorzystanie klonowania strukturalnego było FF. Wysłanie pliku ArrayBuffer
o wielkości 32 MB do pracownika i opublikowanie go w wątku głównym trwało średnio 302 ms (RRT – czas w obie strony). Dla porównania z tymi z możliwością przeniesienia ten sam test trwał 6, 6 ms. To wielki wzrost wydajności!
Przy takich prędkościach ogromne tekstury i siatki WebGL mogą być płynnie przekazywane między platformą roboczą a aplikacją główną.
Wykrywanie funkcji
W tym przypadku wykrywanie funkcji jest nieco skomplikowane. Zalecamy wysłanie do pracownika niewielkiego dodatku ArrayBuffer
. Jeśli bufor został przeniesiony, a nie skopiowany, jego .byteLength
otrzyma wartość 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: Chrome 17 i nowsze wersje, Firefox, Opera, Safari oraz IE10 i nowsze
Aktualizacja (13.12.2011): fragment kodu pokazujący podpis webkitPostMessage()
jest inny w przypadku okna i instancji roboczej.
Aktualizacja (03.11.2016): usunęliśmy prefiksy dostawców i zaktualizowane fragmenty kodu