Domovská » Kódování » Úvod do sdílené paměti v jazyce JavaScript

    Úvod do sdílené paměti v jazyce JavaScript

    Sdílená paměť je pokročilá funkce JavaScriptu, že vlákna (souběžně prováděné části procesu) mohou využít. Sdílení paměti znamená nemá potíže s předáváním aktualizovaných dat mezi vlákny a všechna vlákna mohou přistupovat a aktualizovat stejná data ve sdílené paměti.

    Nezní to hezky? Téměř. V tomto příspěvku uvidíme jak používat sdílenou paměť v JavaScriptu a jak se rozhodnout, zda je to to, co opravdu chcete udělat.

    Výhody a nevýhody sdílené paměti

    Používáme webové pracovníky na vytvořit vlákna v JavaScriptu. Web Workers API nám umožňuje vytvářet pracovní vlákna, na které lze použít spustit kód na pozadí tak, aby hlavní vlákno mělo možnost pokračovat v provádění, případně zpracovávat události UI, což nezajišťuje žádné zmrazení uživatelského rozhraní.

    Pracovní vlákna souběžně s hlavním vláknem a navzájem. Takové současné provádění různých částí úkolu je časově úsporné. Dokončete rychleji, ale má také svůj vlastní soubor problémů.

    Ujistěte se, že každé vlákno získává potřebné zdroje a včas komunikuje je úkol sám o sobě, kde neštěstí může mít za následek překvapivý výsledek. Nebo když jedno vlákno mění data a další čte ve stejnou dobu, co si myslíte, že ostatní vlákno uvidí? Aktualizovaná nebo stará data?

    Weboví pracovníci však nejsou tak snadno sešroubovatelní. Během komunikace prostřednictvím zpráv jsou data, která si navzájem posílají není originál, ale kopie, což znamená, že ne podíl stejná data. oni předávat kopie dat když je potřeba.

    Sdílení je však péče a více vláken může také potřebovat podívat se na stejná data najednou a změnit je. Tak, zákaz sdílení je velký ne-ne. Toto je místo, kde SharedArrayBuffer objekt vstoupí do obrázku. To nám dovolí sdílení binárních dat mezi více podprocesy.

    SharedArrayBuffer objekt

    Namísto předávání datových kopií mezi vlákny, my předat kopie SharedArrayBuffer objekt. A SharedArrayBuffer objekt ukazuje na paměť, do které jsou data uložena.

    Takže, i když kopie SharedArrayBuffer jsou předávány mezi vlákny vše bude stále ukazovat na stejnou paměť kde jsou uložena původní data. Závity tak mohou zobrazovat a aktualizovat data ve stejné paměti.

    Weboví pracovníci bez sdílené paměti

    Abychom zjistili, jak webový pracovník pracuje bez použití sdílené paměti, my vytvořit pracovní vlákno a předat data.

    index.html soubor má hlavní skript uvnitř tag, jak vidíte níže:

     const w = nový pracovník ('worker.js'); var n = 9; w.postMessage (n); 

    worker.js nese soubor pracovní skript:

     onmessage = (e) => console.group ('[pracovník]'); console.log ('Data přijatá z hlavního vlákna:% i', e.data); console.groupEnd ();  

    Pomocí výše uvedeného kódu dostaneme následující výstup v konzole:

     [pracovník] Data přijatá z hlavního vlákna: 9 

    Můžete si přečíst můj výše uvedený příspěvek na webové pracovníky pro úplné vysvětlení kódů výše uvedených úryvků.

    Prozatím mějte na paměti, že data jsou mezi vlákny za použití postMessage () metoda. Data jsou na druhé straně zpráva obsluha události, jako hodnota události data vlastnictví.

    Teď, když my změnit data se objeví na přijímacím konci aktualizován? Uvidíme:

     const w = nový pracovník ('worker.js'); var n = 9; w.postMessage (n); n = 1; 

    Podle očekávání dat ne byly aktualizovány:

     [pracovník] Data přijatá z hlavního vlákna: 9 

    Proč by to tak bylo? To je jen klon odeslaný pracovníkovi z hlavního skriptu.

    Weboví pracovníci s sdílené paměti

    Teď to uděláme používat SharedArrayBuffer objekt ve stejném příkladu. Můžeme vytvořit nový SharedArrayBuffer například za použití Nový klíčové slovo. Konstruktor má jeden parametr; A délka v bajtech, specifikuje velikost vyrovnávací paměti.

     const w = nový pracovník ('worker.js'); buff = new SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * data nastavení * / arr [0] = 9; / * odeslání bufferu (kopie) pracovníku * / w.postMessage (buff); 

    Všimněte si, že a SharedArrayBuffer objekt představuje pouze oblast sdílené paměti. Na zobrazit a změnit binární data, musíme použít vhodnou datovou strukturu (a TypedArray nebo DataView objekt).

    V index.html soubor výše, nový SharedArrayBuffer je vytvořen, pouze s jednou bajtovou délkou. Pak nový Int8Array, což je jeden typ TypedArray objekty nastavte data na “9” v poskytnutém byte prostoru.

     onmessage = (e) => var arr = new Int8Array (e.data); console.group („[pracovník]“); console.log ('Data přijatá z hlavního vlákna:% i', arr [0]); console.groupEnd ();  

    Int8Array je také používán u pracovníka zobrazit data ve vyrovnávací paměti.

    v konzole se zobrazí očekávaná hodnota z pracovního vlákna, což je přesně to, co jsme chtěli:

     [pracovník] Data přijatá z hlavního vlákna: 9 

    Pojďme aktualizovat data v hlavním vláknu zjistit, zda se změna projevuje v pracovníku.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * data nastavení * / arr [0] = 9; / * odeslání bufferu (kopie) pracovníku * / w.postMessage (buff); / * změna dat * / arr [0] = 1;

    A jak vidíte níže, aktualizace odráží uvnitř pracovníka!

     [pracovník] Data přijatá z hlavního vlákna: 1 

    Ale také kód potřebuje pracovat opačně: když se hodnota v pracovníku změní nejprve, je to také aktualizovat při tisku z hlavního vlákna.

    V tomto případě vypadá náš kód takto:

     onmessage = (e) => var arr = new Int8Array (e.data); console.group („[pracovník]“); console.log ('Data přijatá z hlavního vlákna:% i', arr [0]); console.groupEnd (); / * změna dat * / arr [0] = 7; / * odeslání do hlavního vlákna * / postMessage ("); 

    data v pracovníku změněna a prázdná zpráva je odeslána do hlavního vlákna signalizace, že data ve vyrovnávací paměti byla změněna a je připravena na výstup hlavního vlákna.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * data nastavení * / arr [0] = 9; / * odeslání bufferu (kopie) pracovníku * / w.postMessage (buff); / * změna dat * / arr [0] = 1; / * tisk dat po změně pracovníka * / w.onmessage = (e) => console.group ('[hlavní]'); console.log ('Aktualizovaná data přijatá z pracovního vlákna:% i', arr [0]); console.groupEnd ();  

    A to funguje taky! Data ve vyrovnávací paměti jsou stejná jako data uvnitř pracovníka.

     [pracovník] Data přijatá z hlavního vlákna: 1 [hlavní] Aktualizovaná data přijatá z pracovního vlákna: 7 

    Hodnota v obou případech aktualizován; hlavní i pracovní podprocesy prohlíží a mění stejná data.

    Závěrečná slova

    Jak jsem zmínil dříve, pomocí sdílené paměti v JavaScriptu není bez downsides. Je na vývojářích, aby zajistili, že sekvence provedení se děje podle očekávání a žádná dvě vlákna se nesetkají s cílem získat stejná data, protože nikdo neví, kdo bude mít trofej.

    Pokud máte zájem o více sdílené paměti, podívejte se na dokumentaci Atomika objekt. Objekt Atomics vám může pomoci s některými těžkostmi, omezením nepředvídatelné povahy čtení / zápisu ze sdílené paměti.