Introduksjon til delt minne i JavaScript
Delt minne er en avansert funksjon av JavaScript, at tråder (samtidig utførte deler av en prosess) kan utnytte. Deling av minnet betyr Har ikke problemer med å sende oppdaterte data mellom tråder og alle tråder kan få tilgang til og oppdatere de samme dataene i det delte minnet.
Lyder det ikke herlig? Vel, nesten. I dette innlegget ser vi Slik bruker du delt minne i JavaScript og hvordan du bestemmer om dette er det du virkelig vil gjøre.
Fordeler og ulemper med delt minne
Vi bruker webarbeidere til Lag tråder i JavaScript. Webarbeideren API gir oss mulighet til å lage arbeidstråder som kan brukes til Kjør kode i bakgrunnen slik at hovedtråden er fri til å fortsette utførelsen, muligens behandle brukergrensesnitt, slik at ingen UI-fryse blir sikret.
Arbeider tråder Kjør samtidig med hovedtråden og hverandre. Slik samtidig utførelse av ulike deler av en oppgave er tidsbesparende. Du er ferdig raskere, men den har også sitt eget sett med problemer.
Pass på at hver tråd får de nødvendige ressursene og kommuniserer med hverandre i tide er en oppgave i seg selv, der et uhell kan resultere i et overraskende utfall. Eller hvis en tråd endrer data og en annen leser den samtidig, hva tror du den andre tråden vil se? Den oppdaterte eller de gamle dataene?
Imidlertid er webarbeidere ikke så lett å skru opp. Under kommunikasjonen via bruk av meldinger, er dataene de sender hverandre ikke original, men en kopi, noe som betyr at de ikke gjør det dele de samme dataene. De send kopier av data til hverandre når det trengs.
Men deling er omhyggelig, og flere tråder kan også trenge å se på de samme dataene samtidig, og endre dem. Så, forbud mot deling er et stort nei-nei. Det er her SharedArrayBuffer
objekt kommer inn i bildet. Det vil la oss dele binære data mellom flere tråder.
De SharedArrayBuffer
gjenstand
I stedet for å sende data kopiene mellom tråder, vi send kopier av SharedArrayBuffer
gjenstand. EN SharedArrayBuffer
gjenstand peker på minnet der dataene er lagret.
Så, selv når kopier av SharedArrayBuffer
er passert mellom tråder, de alle vil fortsatt peke på det samme minnet hvor de opprinnelige dataene er lagret. Trådene kan således se og oppdatere dataene i det samme minnet.
Webarbeidere uten delt minne
For å se hvordan en webarbeider jobber uten å bruke delt minne, vi Lag en arbeidstråd og send noen data til den.
De index.html
filen holder hovedskript inne i a tag, som du kan se det nedenfor:
const w = ny Arbeider ('worker.js'); var n = 9; w.postMessage (n);
De worker.js
filen bærer arbeider skript:
onmessage = (e) => console.group ('[worker]'); console.log ('Data mottatt fra hovedtråden:% i', e.data); console.groupEnd ();
Ved hjelp av koden ovenfor får vi følgende utgang i konsollen:
[arbeidstaker] Data mottatt fra hovedtråden: 9
Du kan lese mitt nevnte innlegg på webarbeidere for fullkodeforklaring av de ovennevnte kodene.
For nå, husk at dataene er sendt frem og tilbake mellom trådene bruker postmessage ()
metode. Dataene er mottatt på den andre siden av budskap
hendelseshåndterer, som verdien av arrangementet data
eiendom.
Nå, hvis vi endre dataene vil det vises oppdatert i mottakssiden? La oss se:
const w = ny Arbeider ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Som forventet, vil data har ikke blitt oppdatert:
[arbeidstaker] Data mottatt fra hovedtråden: 9
Hvorfor ville det være, uansett? Det er bare en klone sendt til arbeideren fra hovedskriptet.
Webarbeidere med delt minne
Nå vil vi bruke SharedArrayBuffer
gjenstand i samme eksempel. Vi kan lage en ny SharedArrayBuffer
forekomst av bruker ny
søkeord. Konstruktøren tar en parameter; en lengdeverdi i byte, angir størrelsen på bufferen.
const w = ny Arbeider ('worker.js'); buff = ny SharedArrayBuffer (1); var arr = ny Int8Array (buff); / * innstillingsdata * / arr [0] = 9; / * sende bufferen (kopi) til arbeideren * / w.postMessage (buff);
Merk at a SharedArrayBuffer
gjenstand representerer bare et delt minneområde. Til se og endre binære data, vi må bruke en passende datastruktur (a TypedArray
eller a Dataview
gjenstand).
I index.html
filen ovenfor, en ny SharedArrayBuffer
er opprettet, med bare en byte lengde. Så en ny Int8Array
, som er en type av TypedArray
gjenstander, er vant til sett dataene til “9” i den medfølgende byteplassen.
onmessage = (e) => var ar = ny Int8Array (e.data); console.group ( '[arbeideren]'); console.log ('Data mottatt fra hovedtråden:% i', arr [0]); console.groupEnd ();
Int8Array
brukes også i arbeideren til se dataene i bufferen.
De forventet verdi vises i konsollen fra arbeideren tråden, som er akkurat det vi ønsket:
[arbeidstaker] Data mottatt fra hovedtråden: 9
La oss nå oppdater dataene i hovedtråden for å se om endringen reflekteres i arbeideren.
const w = ny Arbeider ('worker.js'), buff = ny SharedArrayBuffer (1); var arr = ny Int8Array (buff); / * innstillingsdata * / arr [0] = 9; / * sende bufferen (kopi) til arbeideren * / w.postMessage (buff); / * Endre dataene * / arr [0] = 1;
Og, som du kan se nedenfor, oppdateringen reflekterer inne i arbeideren!
[arbeidstaker] Data mottatt fra hovedtråden: 1
Men koden også må jobbe den andre veien rundt: Når verdien i arbeideren endrer seg først, det må også oppdateres når den er trykt fra hovedtråden.
I dette tilfellet ser vår kode slik ut:
onmessage = (e) => var ar = ny Int8Array (e.data); console.group ( '[arbeideren]'); console.log ('Data mottatt fra hovedtråden:% i', arr [0]); console.groupEnd (); / * Endre dataene * / arr [0] = 7; / * postering til hovedtråden * / postMessage (");
De data er endret i arbeideren og en Tom melding sendes til hovedtråden signalerer at dataene i bufferen er endret og er klar for at hovedtråden skal sendes ut.
const w = ny Arbeider ('worker.js'), buff = ny SharedArrayBuffer (1); var arr = ny Int8Array (buff); / * innstillingsdata * / arr [0] = 9; / * sende bufferen (kopi) til arbeideren * / w.postMessage (buff); / * Endre dataene * / arr [0] = 1; / * skriver ut data etter at arbeideren har endret den * / w.onmessage = (e) => console.group ('[main]'); console.log ('Oppdaterte data mottatt fra arbeidstråd:% i', arr [0]); console.groupEnd ();
Og dette fungerer også! Dataene i bufferen er de samme som dataene i arbeideren.
[arbeidstaker] Data mottatt fra hovedtråden: 1 [main] Oppdaterte data mottatt fra arbeidstråd: 7
Verdien vises oppdatert i begge tilfellene; både hoved- og arbeidstrådene ser og endrer de samme dataene.
Siste ord
Som jeg tidligere har nevnt, bruker jeg delt minne i JavaScript er ikke uten ulemper. Det er opp til utviklere for å sikre at sekvens av utførelse skjer som spådd og ingen to tråder løper for å få de samme dataene fordi ingen vet hvem som skal ta troféet.
Hvis du er interessert i delt minne mer, ta en titt på dokumentasjonen til Atomics
gjenstand. De Atomics objekt kan hjelpe deg med noen av vanskelighetene, ved å redusere uforutsigbarheten av lesing / skriving fra det felles minnet.