Wydajna pamięć aplikacji: Storage Foundation API

Platforma internetowa coraz częściej oferuje deweloperom narzędzia potrzebne do tworzenia zoptymalizowanych pod kątem wydajnych aplikacji internetowych. Przede wszystkim technologia WebAssembly (Wasm) umożliwiła korzystanie z szybkich i zaawansowanych aplikacji internetowych, natomiast technologie takie jak Emscripten umożliwiają teraz deweloperom wykorzystywanie wypróbowanego i przetestowanego kodu w internecie. Aby w pełni wykorzystać ten potencjał, deweloperzy muszą mieć niezmienną moc i elastyczność w zakresie miejsca na dane.

Tutaj z pomocą przyszedł interfejs Storage Foundation API. Storage Foundation API to nowy, szybki i nieokreślony interfejs API do przechowywania danych, który odblokowuje nowe i często bardzo pożądane przypadki użycia w internecie, takie jak wdrażanie wydajnych baz danych i płynne zarządzanie dużymi plikami tymczasowymi. Dzięki nowemu interfejsowi deweloperzy mogą „udostępnić własne miejsce na dane” w internecie, co zmniejszy liczbę funkcji między kodem internetowym a kodem na danej platformie.

Interfejs Storage Foundation API został zaprojektowany tak, aby przypominał bardzo podstawowy system plików. Zapewnia on programistom elastyczność, dając przy tym ogólne, proste i wydajne podstawowe elementy, na których mogą tworzyć bardziej zaawansowane komponenty. Mogą korzystać z najlepszych narzędzi, które odpowiadają ich potrzebom, i zachowywać odpowiednią równowagę między łatwością, wydajnością i niezawodnością.

Dlaczego sieć potrzebuje innego interfejsu API do przechowywania danych?

Platforma internetowa oferuje deweloperom wiele opcji miejsca na dane, z których każda została stworzona z myślą o konkretnych przypadkach użycia.

  • Część z tych opcji wyraźnie nie pokrywa się z tą propozycją, ponieważ umożliwiają przechowywanie bardzo niewielkich ilości danych, np. plików cookie lub interfejsu Web Storage API składającego się z mechanizmów sessionStorage i localStorage.
  • Inne opcje zostały już wycofane z różnych powodów, takich jak File and Directory pozwolenie API lub WebSQL.
  • Interfejs File System Access API ma podobną platformę interfejsu API, ale jego przeznaczeniem jest łączenie się z systemem plików klienta i zapewnianie dostępu do danych, które mogą być poza źródłem lub nawet do przeglądarki. Takie podejście wiąże się z bardziej rygorystycznymi kwestiami bezpieczeństwa i wyższymi kosztami wydajności.
  • Interfejs IndexedDB API może być używany jako backend w niektórych przypadkach użycia interfejsu Storage Foundation API. Na przykład Emscripten obejmuje IDBFS, system plików oparty na IndexedDB. Ponieważ IndexedDB jest zasadniczo magazynem par klucz-wartość, wiąże się to z znacznymi ograniczeniami wydajności. Ponadto bezpośredni dostęp do podsekcji pliku jest jeszcze trudniejszy i wolniejszy w przypadku IndexedDB.
  • Na koniec interfejs CacheStorage jest powszechnie obsługiwany i został przystosowany do przechowywania danych o dużej wielkości, takich jak zasoby aplikacji internetowych, ale ich wartości są stałe.

Interfejs Storage Foundation API jest próbą rozwiązania wszystkich luk w zabezpieczeniach, które występują w poprzednich opcjach miejsca na dane, umożliwiając wydajne przechowywanie zmiennych dużych plików zdefiniowanych w źródle aplikacji.

Sugerowane przypadki użycia interfejsu Storage Foundation API

Przykłady witryn, które mogą używać tego interfejsu API:

  • Aplikacje zwiększające produktywność lub pobudzające kreatywność, które wykorzystują duże ilości danych wideo, audio lub obrazów. Takie aplikacje mogą przenosić segmenty na dysk zamiast zatrzymywać je w pamięci.
  • aplikacje, które korzystają z trwałego systemu plików dostępnego przez Wasm i potrzebują większej wydajności, niż może to zagwarantować IDBFS.

Czym jest interfejs Storage Foundation API?

Interfejs API składa się z 2 głównych elementów:

  • Wywołania systemu plików, które zapewniają podstawowe funkcje interakcji z plikami i ścieżkami do plików.
  • Uchwyty plików – uprawnienia do odczytu i zapisu istniejącego pliku.

Wywołania systemu plików

Interfejs Storage Foundation API wprowadza nowy obiekt storageFoundation, który znajduje się w obiekcie window i zawiera wiele funkcji:

  • storageFoundation.open(name): otwiera plik o podanej nazwie (jeśli istnieje) i w przeciwnym razie tworzy nowy plik. Zwraca obietnicę, która znika w otwartym pliku.
  • storageFoundation.delete(name): usuwa plik o podanej nazwie. Zwraca obietnicę, która znika po usunięciu pliku.
  • storageFoundation.rename(oldName, newName): zmienia nazwę pliku ze starej na nową. Zwraca obietnicę, która znika po zmianie nazwy pliku.
  • storageFoundation.getAll(): zwraca obietnicę, która znika za pomocą tablicy wszystkich istniejących nazw plików.
  • storageFoundation.requestCapacity(requestedCapacity): żąda nowej pojemności (w bajtach) do wykorzystania przez bieżący kontekst wykonania. Zwraca obietnicę, która została osiągnięta przy pozostałej dostępnej mocy obliczeniowej.
  • storageFoundation.releaseCapacity(toBeReleasedCapacity): zwalnia określoną liczbę bajtów z bieżącego kontekstu wykonania i zwraca obietnicę, która znika przy pozostałej pojemności.
  • storageFoundation.getRemainingCapacity(): zwraca obietnicę, która znika w przypadku mocy dostępnej w bieżącym kontekście wykonania.

Uchwyty pliku

Praca z plikami odbywa się za pomocą następujących funkcji:

  • NativeIOFile.close(): zamyka plik i zwraca obietnicę, która znika po zakończeniu operacji.
  • NativeIOFile.flush(): synchronizuje (czyli usuwa) stan w pamięci pliku z urządzeniem pamięci masowej i zwraca obietnicę, która znika po zakończeniu operacji.
  • NativeIOFile.getLength(): zwraca obietnicę, która znika wraz z długością pliku w bajtach.
  • NativeIOFile.setLength(length): ustawia długość pliku w bajtach i zwraca obietnicę, która rozwiązuje się po zakończeniu operacji. Jeśli nowa długość jest mniejsza niż obecna, bajty będą usuwane, zaczynając od końca pliku. W przeciwnym razie plik zostanie wydłużony o bajty o wartości zerowej.
  • NativeIOFile.read(buffer, offset): odczytuje zawartość pliku przy danym przesunięciach za pomocą bufora w wyniku przesyłania danego bufora, który zostaje odłączony. Zwraca NativeIOReadResult z przeniesionym buforem i liczbą bajtów, które zostały odczytane.

    NativeIOReadResult to obiekt składający się z 2 wpisów:

    • buffer: ArrayBufferView w wyniku przeniesienia bufora przekazanego do read(). Typ i długość są tego samego typu co bufor źródła.
    • readBytes: liczba bajtów odczytanych przez funkcję buffer. Jeśli wystąpi błąd lub zakres odczytu wykracza poza koniec pliku, może on być mniejszy niż rozmiar bufora. Jeśli zakres odczytu wykracza poza koniec pliku, ma ona wartość 0.
  • NativeIOFile.write(buffer, offset): zapisuje zawartość danego bufora w pliku z podanym przesunięciem. Bufor jest przesyłany przed zapisaniem danych, więc pozostaje odłączony. Zwraca NativeIOWriteResult z przeniesionym buforem i liczbą bajtów, które zostały zapisane. Jeśli długość zakresu zapisu przekroczy długość pliku, plik zostanie rozszerzony.

    NativeIOWriteResult to obiekt składający się z 2 wpisów:

    • buffer: ArrayBufferView w wyniku przeniesienia bufora przekazanego do write(). Ma ten sam typ i długość co bufor źródłowy.
    • writtenBytes: liczba bajtów, które zostały zapisane w komórce buffer. W przypadku błędu wartość ta może być mniejsza niż rozmiar bufora.

Pełne przykłady

Aby ujednolicić przedstawione powyżej pojęcia, przedstawiamy 2 pełne przykłady, które przeprowadzą Cię przez różne etapy cyklu życia plików Podstawy miejsca na dane.

Otwieranie, pisanie, czytanie, zamykanie

// Open a file (creating it if needed).
const file = await storageFoundation.open('test_file');
try {
  // Request 100 bytes of capacity for this context.
  await storageFoundation.requestCapacity(100);

  const writeBuffer = new Uint8Array([64, 65, 66]);
  // Write the buffer at offset 0. After this operation, `result.buffer`
  // contains the transferred buffer and `result.writtenBytes` is 3,
  // the number of bytes written. `writeBuffer` is left detached.
  let result = await file.write(writeBuffer, 0);

  const readBuffer = new Uint8Array(3);
  // Read at offset 1. `result.buffer` contains the transferred buffer,
  // `result.readBytes` is 2, the number of bytes read. `readBuffer` is left
  // detached.
  result = await file.read(readBuffer, 1);
  // `Uint8Array(3) [65, 66, 0]`
  console.log(result.buffer);
} finally {
  file.close();
}

Otwieranie, wyświetlanie listy, usuwanie

// Open three different files (creating them if needed).
await storageFoundation.open('sunrise');
await storageFoundation.open('noon');
await storageFoundation.open('sunset');
// List all existing files.
// `["sunset", "sunrise", "noon"]`
await storageFoundation.getAll();
// Delete one of the three files.
await storageFoundation.delete('noon');
// List all remaining existing files.
// `["sunrise", "noon"]`
await storageFoundation.getAll();

Wersja demonstracyjna

Możesz obejrzeć prezentację interfejsu Storage Foundation API, którą znajdziesz poniżej. tworzyć pliki, zmieniać ich nazwy, zapisywać w nich dane i je odczytywać, a także wyświetlać dostępne miejsce na dane, o które prosisz podczas wprowadzania zmian. Kod źródłowy wersji demonstracyjnej znajdziesz na stronie Glitch.

Zabezpieczenia i uprawnienia

Zespół Chromium opracował i wdrożył interfejs Storage Foundation API zgodnie z podstawowymi zasadami określonymi w artykule Kontrolowanie dostępu do zaawansowanych funkcji platformy internetowej, w tym dotyczących kontroli użytkownika, przejrzystości i ergonomii.

Zgodnie z tym samym wzorcem co inne internetowe interfejsy API do przechowywania danych dostęp do interfejsu Storage Foundation API jest uzależniony od źródła, co oznacza, że źródło może uzyskiwać dostęp tylko do danych utworzonych przez siebie. Ogranicza się też do bezpiecznych kontekstów.

Kontrola użytkowników

Limit miejsca na dane będzie wykorzystywany do rozdzielania dostępu do miejsca na dysku i zapobiegania nadużyciom. Pamięć, którą chcesz zająć, musi zostać najpierw zamówiona. Podobnie jak w przypadku innych interfejsów API pamięci masowej, użytkownicy mogą zwolnić miejsce zajmowane przez Storage Foundation API w przeglądarce.

Przydatne linki

Podziękowania

Interfejs Storage Foundation API został określony i wdrożony przez Emanuela Krivoya i Richarda Stotza. Ten artykuł został zweryfikowany przez Pete LePage i Joe Medley.

Baner powitalny autorstwa: Markus Spiske w serwisie Unsplash.