Úvod do zdieľanej pamäte v jazyku JavaScript
Zdieľaná pamäť je pokročilá funkcia jazyka JavaScript, ktorá môže využívať vlákna (súbežne vykonané časti procesu). Zdieľanie pamäťových prostriedkov bez problémov s prenášaním aktualizovaných údajov medzi vláknami a všetky vlákna môžu pristupovať a aktualizovať rovnaké údaje v zdieľanej pamäti.
Nie je to pekné? No, skoro. V tomto príspevku uvidíme ako používať zdieľanú pamäť v jazyku JavaScript a ako sa rozhodnúť, či to naozaj chcete urobiť.
Výhody a nevýhody zdieľanej pamäte
Používame web pracovníkov na vytvárať vlákna v jazyku JavaScript. Aplikácia Web Workers API nám umožňuje vytvárať pracovné podprocesy, ktoré je možné použiť spustiť kód na pozadí takže hlavná niť je schopná pokračovať v jej vykonávaní, eventuálne spracovávať UI udalosti a zabezpečiť, aby nebolo zmrazené používateľské rozhranie.
Pracovné vlákna bežať súčasne s hlavným vláknom a navzájom. Takéto simultánne vykonávanie rôznych častí úlohy je časovo úsporné. Dokončíte rýchlejšie, ale má aj vlastný súbor problémov.
Uistite sa, že každá niť získajú potrebné zdroje a včas komunikujú je sama osebe úloha, keď nešťastie môže mať za následok prekvapujúci výsledok. Alebo ak jeden závit mení dáta a druhý ho číta v rovnakom čase, čo si myslíte, že ostatné vlákno uvidí? Aktualizované alebo staré údaje?
Pracovníci webových stránok však nie sú tak ľahko uviazli. Počas komunikácie prostredníctvom správ sú údaje, ktoré navzájom posielajú, sú nie originál, ale kópia, čo znamená, že nie zdieľam rovnaké údaje. oni odovzdávať kópie údajov navzájom ak je to potrebné.
Zdieľanie sa však stará a viaceré vlákna by sa mali súčasne pozerať na rovnaké dáta a meniť ich. tak, zákaz zdieľania je veľký nie-nie. Toto je miesto, kde SharedArrayBuffer
objekt dostane do obrazu. To nám to dovolí zdieľanie binárnych údajov medzi viacerými vláknami.
SharedArrayBuffer
objekt
Namiesto toho, aby sme preniesli kópie údajov medzi vláknami, my predložiť kópie SharedArrayBuffer
objekt. SharedArrayBuffer
objekt ukazuje na pamäť, kde sú uložené dáta.
Takže, aj keď kópie SharedArrayBuffer
prechádzajú medzi vláknami, oni všetko bude stále smerovať do rovnakej pamäte kde sú uložené pôvodné údaje. Takže vlákna môžu prezerať a aktualizovať údaje v tej istej pamäti.
Web pracovníkov bez zdieľaná pamäť
Ak chcete vidieť, ako pracuje webový pracovník bez použitia zdieľanej pamäte, my vytvoriť pracovnú niť a odovzdať niektoré údaje.
index.html
súbor obsahuje hlavný skript vnútri a ako vidíte nižšie:
const w = nový pracovník ("worker.js"); var n = 9; w.postMessage (n);
worker.js
súbor nesie pracovný skript:
onmessage = (e) => console.group ('[pracovník]'); console.log ('Dáta prijaté z hlavného vlákna:% i', e.data); console.groupEnd ();
Pomocou vyššie uvedeného kódu získame nasledovné výstup v konzole:
[pracovník] Údaje získané z hlavného vlákna: 9
Môžete si prečítať môj vyššie uvedený príspevok na pracovníkov webových stránok s cieľom úplného vysvetlenia kódov uvedených úryvkov.
Zatiaľ majte na pamäti, že údaje sú odoslané sem a tam medzi vláknami pomocou PostMessage ()
metóda. Údaje sú prijatý na druhej strane správa
obsluha udalosti, ako hodnota udalosti dáta
vlastnosť.
Teraz, ak sme my zmeniť údaje bude sa zobrazovať aktualizované na konci príjemcu? Pozrime sa:
const w = nový pracovník ("worker.js"); var n = 9; w.postMessage (n); n = 1;
Ako sa očakávalo má dáta nie boli aktualizované:
[pracovník] Údaje získané z hlavného vlákna: 9
Prečo by to tak bolo? to je len klon poslaný pracovníkovi z hlavného scenára.
Web pracovníkov s zdieľaná pamäť
Teraz budeme Použi SharedArrayBuffer
objekt v tom istom príklade. Môžeme vytvoriť nový SharedArrayBuffer
napr pomocou Nový
kľúčových slov. Konštruktor má jeden parameter; dĺžková hodnota v bajtoch, špecifikovať veľkosť vyrovnávacej pamäte.
const w = nový pracovník ("worker.js"); buff = nový SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * nastavenie dát * / arr [0] = 9; / * odoslanie vyrovnávacej pamäte (kópia) pracovníkovi * / w.postMessage (buff);
Upozorňujeme, že a SharedArrayBuffer
objekt predstavuje iba oblasť zdieľanej pamäte. na vidieť a meniť binárne údaje, musíme použiť vhodnú dátovú štruktúru (a TypedArray
alebo a DataView
objekt).
V index.html
súbor vyššie, nový SharedArrayBuffer
je vytvorený len s dĺžkou jedného bajtu. Potom nový Int8Array
, čo je jeden typ TypedArray
objekty, ktoré sa používajú nastavte dáta na “9” v poskytnutom bajtovom priestore.
onmessage = (e) => var arr = nová Int8Array (e.data); console.group ( '[pracovník]'); console.log ('Dáta prijaté z hlavného vlákna:% i', arr [0]); console.groupEnd ();
Int8Array
sa tiež používa u pracovníka, na zobraziť údaje v vyrovnávacej pamäti.
v konzole sa zobrazí očakávaná hodnota z pracovnej nite, čo je presne to, čo sme chceli:
[pracovník] Údaje získané z hlavného vlákna: 9
Teraz, poďme aktualizovať údaje v hlavnom vlákne či sa zmena prejaví v pracovníkovi.
const w = nový pracovník ('worker.js'), buff = nový SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * nastavenie dát * / arr [0] = 9; / * odoslanie vyrovnávacej pamäte (kópia) pracovníkovi * / w.postMessage (buff); / * zmena dát * / arr [0] = 1;
A ako vidíte nižšie, aktualizácia sa odráža vo vnútri pracovníka!
[pracovník] Údaje získané z hlavného vlákna: 1
Ale aj kód musí pracovať opačne: keď sa najskôr mení hodnota v zamestnancovi, je to je tiež potrebné aktualizovať keď je vytlačená z hlavného vlákna.
V tomto prípade náš kód vyzerá takto:
onmessage = (e) => var arr = nová Int8Array (e.data); console.group ( '[pracovník]'); console.log ('Dáta prijaté z hlavného vlákna:% i', arr [0]); console.groupEnd (); / * zmena údajov * / arr [0] = 7; / * odoslanie do hlavného vlákna * / postMessage (");
dáta sa zmenia v pracovníkovi a an prázdna správa sa uverejní na hlavnom vlákne že údaje v vyrovnávacej pamäti boli zmenené a je pripravený na výstup hlavného vlákna.
const w = nový pracovník ('worker.js'), buff = nový SharedArrayBuffer (1); var arr = nový Int8Array (buff); / * nastavenie dát * / arr [0] = 9; / * odoslanie vyrovnávacej pamäte (kópia) pracovníkovi * / w.postMessage (buff); / * zmena dát * / arr [0] = 1; / * tlač údajov po tom, ako ich zmenil pracovník * / w.onmessage = (e) => console.group ('[main]'); console.log ("Aktualizované údaje prijaté z pracovného vlákna:% i", arr [0]); console.groupEnd ();
A to funguje tiež! Údaje v vyrovnávacej pamäti sú rovnaké ako dáta vo vnútri pracovníka.
[pracovník] Údaje získané z hlavného vlákna: 1 [hlavná] Aktualizované údaje doručené od pracovníka vlákno: 7
Hodnota v obidvoch prípadoch sa zdá byť aktualizovaný; hlavné a pracovné vlákna zobrazujú a menia rovnaké údaje.
Záverečné slová
Ako som už spomínal, pomocou zdieľanej pamäte v jazyku JavaScript nie je bez downsides. Je na vývojárov, aby zabezpečili, že postupnosť vykonávania sa deje podľa predpovede a žiadne dve vlákna sa dostihajú, aby získali rovnaké údaje, pretože nikto nevie, kto získa trofej.
Ak máte záujem o zdieľanú pamäť viac, pozrite sa na dokumentáciu atómovej
objekt. Atómový objekt vám môže pomôcť s niektorými ťažkosťami, znížením nepredvídateľnej povahy čítania / zápisu zo zdieľanej pamäte.