Uvod v skupni pomnilnik v JavaScriptu
Skupni pomnilnik je napredna funkcija JavaScripta, da lahko niti (sočasno izvedeni deli procesa) izkoristijo. Skupna raba pomnilniških sredstev nimajo težav pri posredovanju posodobljenih podatkov med nitmi in vse niti lahko dostopajo in posodabljajo iste podatke v skupnem pomnilniku.
Ali to ne zveni čudovito? No, skoraj. Na tem mestu bomo videli kako uporabljati skupni pomnilnik v JavaScriptu in kako se odločiti, ali je to tisto, kar si resnično želite.
Prednosti in slabosti skupnega spomina
Uporabljamo spletni delavci do ustvarite niti v JavaScriptu. API Web Workers nam omogoča, da ustvarimo delovne niti, ki jih lahko uporabite izvršite kodo v ozadju tako, da lahko glavna nit nadaljuje svojo izvedbo, morda obdeluje dogodke uporabniškega vmesnika, pri tem pa ne zagotavlja zamrznitve uporabniškega vmesnika.
Delovne niti teči hkrati z glavno nitjo in med seboj. Tako hkratno izvajanje različnih delov naloge je prihranek časa. Hitreje končate, vendar pa ima tudi svoje probleme.
Zagotavljanje, da je vsaka nit dobi potrebne vire in pravočasno komunicira med seboj je naloga sama po sebi, kjer lahko nezgoda privede do presenetljivega izida. Ali, če ena nit spreminja podatke, druga pa jo bere ob istem času, kaj misliš, da bo druga nit videla? Posodobljeni ali stari podatki?
Vendar pa spletni delavci niso tako lahki zajebati. Med komunikacijo preko sporočil se med seboj pošiljajo podatki ni izvirnik, ampak kopija, kar pomeni, da ne deliti enake podatke. Oni posredujte kopije podatkov drug drugemu po potrebi.
Toda souporaba je skrbna in več niti lahko istočasno pogleda na iste podatke in jih spremeni. Torej, prepoved delitve je velik ne-ne. Tukaj je SharedArrayBuffer
predmet pride v sliko. Pustili nam bodo delite binarne podatke med več nizi.
The SharedArrayBuffer
predmet
Namesto posredovanja podatkovnih kopij med niti, mi kopije SharedArrayBuffer
predmet. A SharedArrayBuffer
predmet kaže na pomnilnik, kjer so shranjeni podatki.
Torej, tudi ko kopije SharedArrayBuffer
se prenašajo med nitmi vsi bodo še vedno kazali na isti spomin kjer so shranjene izvirne podatke. Niti lahko tako pregledate in posodobite podatke v istem pomnilniku.
Spletni delavci brez skupni pomnilnik
Da bi videli, kako spletni delavec deluje brez pomnilnika v skupni rabi, ustvarite nit delavca in posredovati nekaj podatkov.
The index.html
Datoteka ima glavni scenarij znotraj oznako, kot jo lahko vidite spodaj:
const w = nov delavec ('worker.js'); var n = 9; w.postMessage (n);
The worker.js
datoteka nosi oznako delavca:
onmessage = (e) => console.group ('[delavec]'); console.log ('Podatki, prejeti iz glavne niti:% i', e.data); console.groupEnd ();
Z uporabo zgornje kode dobimo naslednje izhod v konzoli:
[delavec] Podatki, prejeti iz glavne niti: 9
Moje objave na spletni strani lahko preberete za celotno razlago kode zgoraj navedenih odlomkov.
Za zdaj ne pozabite, da so podatki poslana naprej in nazaj med nitmi uporabljati postMessage ()
metodo. Podatki so na drugi strani. \ t sporočilo
dogodka, kot vrednost dogodka podatkov
nepremičnine.
Zdaj, če bomo spremenite podatke se bo prikazal posodobljen na koncu prejemanja? Pa poglejmo:
const w = nov delavec ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Kot je bilo pričakovano, podatkov ne posodobljen:
[delavec] Podatki, prejeti iz glavne niti: 9
Zakaj bi bilo tako? To je samo klon, poslan delavcu iz glavnega skripta.
Spletni delavci z skupni pomnilnik
Zdaj bomo uporabi SharedArrayBuffer
predmet v istem primeru. Ustvarimo lahko novo SharedArrayBuffer
na primer uporabljati novo
ključno besedo. Konstruktor ima en parameter; a vrednost dolžine v bajtih, ki določa velikost vmesnega pomnilnika.
const w = nov delavec ('worker.js'); buff = new SharedArrayBuffer (1); var arr = novo Int8Array (buff); / * nastavitev podatkov * / arr [0] = 9; / * pošiljanje vmesnega pomnilnika (kopija) delavcu * / w.postMessage (buff);
Upoštevajte, da a SharedArrayBuffer
predmet predstavlja samo območje pomnilnika v skupni rabi. Za glej in spremeni binarne podatke, uporabljati moramo ustrezno strukturo podatkov (a TypedArray
ali a DataView
predmet).
V index.html
zgoraj, nov SharedArrayBuffer
je ustvarjena z enojbajtno dolžino. Potem pa novo Int8Array
, ki je ena vrsta TypedArray
predmetov nastavite podatke “9” v predvidenem bajtnem prostoru.
onmessage = (e) => var arr = novo Int8Array (e.data); console.group ("[delavec]"); console.log ('Podatki, prejeti iz glavne niti:% i', arr [0]); console.groupEnd ();
Int8Array
se uporablja tudi pri delavcu, do Oglejte si podatke v medpomnilniku.
The v konzoli se prikaže pričakovana vrednost iz delovne nitke, kar je točno tisto, kar smo želeli:
[delavec] Podatki, prejeti iz glavne niti: 9
Zdaj pa posodobite podatke v glavni niti da bi ugotovili, ali se sprememba odraža v delavcu.
const w = novo delavca ('worker.js'), buff = novo SharedArrayBuffer (1); var arr = novo Int8Array (buff); / * nastavitev podatkov * / arr [0] = 9; / * pošiljanje vmesnega pomnilnika (kopija) delavcu * / w.postMessage (buff); / * spreminjanje podatkov * / arr [0] = 1;
In, kot vidite spodaj, posodobitev ne odraža znotraj delavca!
[delavec] Podatki, prejeti iz glavne niti: 1
Ampak tudi koda mora obratno obratno: ko se vrednost v delavcu najprej spremeni tudi posodobiti ko je natisnjena iz glavne niti.
V tem primeru je naša koda videti tako:
onmessage = (e) => var arr = novo Int8Array (e.data); console.group ("[delavec]"); console.log ('Podatki, prejeti iz glavne niti:% i', arr [0]); console.groupEnd (); / * spreminjanje podatkov * / arr [0] = 7; / * objavljanje na glavni niti * / postMessage (");
The podatki se spremenijo v delavcu in prazno sporočilo je poslano na glavno nit signaliziranje, da so bili podatki v medpomnilniku spremenjeni in pripravljeni za izhodno glavno nit.
const w = novo delavca ('worker.js'), buff = novo SharedArrayBuffer (1); var arr = novo Int8Array (buff); / * nastavitev podatkov * / arr [0] = 9; / * pošiljanje vmesnega pomnilnika (kopija) delavcu * / w.postMessage (buff); / * spreminjanje podatkov * / arr [0] = 1; / * tiskanje podatkov po tem, ko ga je delavec spremenil * / w.onmessage = (e) => console.group ('[main]'); console.log ("Posodobljeni podatki, prejeti iz delavnice nit:% i ', arr [0]); console.groupEnd ();
Tudi to deluje! Podatki v medpomnilniku so enaki kot podatki znotraj delavca.
[Delavec] Podatki, prejeti iz glavne niti: 1 [glavni] Posodobljeni podatki, prejeti iz delavnice: 7
Vrednost se v obeh primerih posodablja; tako glavne kot delovne niti pregledujejo in spreminjajo iste podatke.
Zadnje besede
Kot sem že omenil, uporabljam skupni pomnilnik v JavaScriptu ni brez slabosti. Razvijalci morajo zagotoviti, da zaporedje izvršitve se zgodi, kot je predvideno in nobena od dveh niti ne tekmuje, da bi dobili iste podatke, ker nihče ne ve, kdo bo prevzel trofejo.
Če vas zanima več skupnega pomnilnika, si oglejte dokumentacijo Atomika
predmet. The Atomski objekt vam lahko pomaga pri nekaterih težavah, z zmanjšanjem nepredvidljive narave branja / pisanja iz skupnega pomnilnika.