Scott Tiger Tech Blog

Blog technologiczny firmy Scott Tiger S.A.

Typed Array

Autor: Piotr Karpiuk o czwartek 12. Lipiec 2012

Rozwój języka JavaScript podąża za zapotrzebowaniem, czego przejawem jest m.in. Typed Arrays – sposób na efektywne przekazywanie danych binarnych do bibliotek natywnych. Jedynym typem liczbowym w JavaScripcie jest typ zmiennoprzecinkowy, a reprezentacja tablicy bajtów zawsze była mało oszczędna pamięciowo (Array) lub niewygodna (np. String.rawCodeAt()). Na nowe typy danych ArrayBuffer, ArrayBufferView i DataView można spojrzeć jak na odpowiedniki tablic i struktur w języku C.

Propozycja nowych rozwiązań wyszła ze strony zespołu pracującego nad WebGL (grafika 3D w przeglądarce), ale szybko znalazły one zastosowanie w takich technologiach przeglądarkowych jak:

  • HTML5 Canvas – fragment płótna można przekształcić w natywną tablicę pikseli i działać bezpośrednio na niej,
  • Web Audio API, Media Source API – dostęp do danych binarnych audio i wideo,
  • XMLHTTPRequest 2, WebSockets – między przeglądarką a serwerem można przesyłać dane binarne,
  • WebWorkers – można przekazywać dane binarne (przez referencję!) między wątkami; przynajmniej w Google Chrome,
  • File API – można manipulować danymi binarnymi na dysku w systemie plików (w piaskownicy).

Nadeszły zatem czasy, gdy programista JavaScriptu po stronie przeglądarki może wygodnie dobrać się do pliku binarnego MP3 lub JPEG aby wyciągnąć z niego metadane.

Mechanizm, o którym dziś mowa, składa się z dwóch części: bufora (klasa ArrayBuffer) i perspektywy (ang. view, klasa ArrayBufferView i pochodne – czyli tablice, oraz DataView – czyli dostęp swobodny). Bufor jest tablicą bajtów, a perspektywa daje dostęp do niego zapewniając kontekst, jakim jest offset startowy bufora, liczba bajtów, i typ danych komórki. Dla jednego bufora możemy utworzyć dowolnie wiele perspektyw.

Tablice

Nazwy klas implementujących perspektywy tablicowe dają pojęcie o typie komórek: Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array.

      var buffer = new ArrayBuffer( 16 ); // bufor 16 wyzerowanych bajtów
      var view = new Int32Array( buffer ); // tablica 4 liczb całkowitych
      for( var i = 0; i < view.length; i++ ) {
        view[i] = i * 2;
      }

      function memcpy(dst, dstOffset, src, srcOffset, length) {
        var dstU8 = new Uint8Array(dst, dstOffset, length);
        var srcU8 = new Uint8Array(src, srcOffset, length);
        dstU8.set(srcU8); // bardzo szybkie kopiowanie danych
      }

DataView

Perspektywa typu DataView daje swobodny dostęp do bufora, pozwalając wyciągać wartość określonego typu liczbowego, z określoną kolejnością bajtów (ang. big endian lub little endian). Załóżmy że mamy dane, w których jest 8-bitowa wartość za którą występują dwie 16-bitowe liczby całkowite, a następnie tablica 32-bitowych liczb zmiennoprzecinkowych.

      var dv = new DataView(buffer);
      var vector_length = dv.getUint8(0);
      var width = dv.getUint16(1, false); // 0+uint8 = 1 bytes offset
      var height = dv.getUint16(3, false); // 0+uint8+uint16 = 3 bytes offset
      var vectors = new Float32Array(width*height*vector_length);
      for (var i=0, off=5; i<vectors.length; i++, off+=4) {
        vectors[i] = dv.getFloat32(off, false);
      }

Parametr false w powyższych wywołaniach oznacza że interesuje nas kolejność bajtów big endian. Oczywiście oprócz metod typu get, mamy też metody set:

      dv.setFloat32( 8, 2.5, true );

Uwaga: kolejność bajtów w perspektywach tablicowych jest zawsze taka sama jak w procesorze wykonującym kod JavaScriptu.

Biblioteki

Kilka bibliotek ułatwiających korzystanie z typed array:

  • stringencoding – ułatwia zapisywanie i odczyt łańcuchów w danych binarnych,
  • DataStream.js – pozwala obsługiwać dane binarne podobnie jak pliki, tj. po każdym odczycie/zapisie automatycznie przesuwa się offset kolejnego odczytu/zapisu.

Literatura

Share and Enjoy:
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Śledzik
  • Blip
  • Blogger.com
  • Gadu-Gadu Live
  • LinkedIn
  • MySpace
  • Wykop

2 Komentarzy do “Typed Array”

  1. Krzysztof napisał(a):

    Ten tekst „(ang. view, klasa ArrayBufferView i pochodne – czyli tablice, oraz DataView – czyli dostęp swobodny)” jest trochę nieprecyzyjnie napisany. Ja na początku zrozumiałem, że tylko tablice są pochodną od ArrayBufferView. Ale przecież (jak wynika ze specyfikacji) DataView też jest klasą pochodną od ArrayBufferView.

  2. Piotr Karpiuk napisał(a):

    Ma Pan rację, dziękuję za zwrócenie uwagi.

Zostaw komentarz

XHTML: Możesz użyć następujących tagów: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>