Johdatus jaettuun muistiin JavaScriptissä
Jaettu muisti on JavaScriptin edistyksellinen piirre, että kierteet (samanaikaisesti suoritetut prosessin osat) voivat hyödyntää. Muistivälineiden jakaminen ei ole vaikeuksia välittää päivitettyjä tietoja langojen välillä ja kaikki langat voivat käyttää ja päivittää samoja tietoja jaetussa muistissa.
Eikö se kuulosta ihanan? No melkein. Tässä viestissä näemme miten jaettua muistia käytetään JavaScriptissä ja miten päättää, onko tämä todella mitä haluat tehdä.
Jaetun muistin edut ja haitat
Käytämme web-työntekijät että luo säikeitä JavaScriptissä. Web Workers API -palvelun avulla voimme luoda työntekijäkierteitä, joita voidaan käyttää suorita koodi taustalla niin, että pääkierre on vapaa jatkamaan suoritusta, mahdollisesti käsittelemään käyttöliittymän tapahtumia, varmistaen, ettei UI: n jäätyä.
Työntekijäkierteet ajetaan samanaikaisesti pääkierteen ja toistensa kanssa. Tehtävän eri osien samanaikainen suorittaminen on aikaa säästävä. Voit lopettaa nopeammin, mutta sillä on myös omia ongelmia.
Varmista, että jokainen kierre saa tarvittavat resurssit ja kommunikoi keskenään ajoissa on tehtävä sinänsä, jossa vika voi johtaa yllättävään lopputulokseen. Tai jos yksi lanka muuttaa tietoja ja toinen lukee sitä samaan aikaan, mitä luulet toisen langan? Päivitetty tai vanha data?
Verkkotyöntekijät eivät kuitenkaan ole kovin helposti kiristettävissä. Viestien välityksellä tapahtuvan viestinnän aikana lähetettävät tiedot ovat ei alkuperäinen mutta kopio, tarkoittaa, että he eivät Jaa samoja tietoja. Ne kopioi tietoja toisilleen tarvittaessa.
Jakaminen on kuitenkin välitöntä, ja useat säikeet saattavat joutua tarkastelemaan samoja tietoja samanaikaisesti ja muuttamaan niitä. Niin, jakamisen kieltäminen on iso no-no. Tässä on SharedArrayBuffer
kohde tulee kuvaan. Se antaa meille jakaa binaaridataa useiden säikeiden välillä.
SharedArrayBuffer
esine
Sen sijaan, että välitettäisiin kopiot kierteiden välillä, me siirtää kopioita SharedArrayBuffer
esine. SharedArrayBuffer
esine osoittaa muistiin, johon tiedot tallennetaan.
Joten, vaikka kopiot SharedArrayBuffer
ne kulkevat kierteiden välillä, ne kaikki osoittavat edelleen samaan muistiin missä alkuperäiset tiedot tallennetaan. Näin kierteet voivat tarkastella ja päivittää tietoja samassa muistissa.
Web-työntekijät ilman jaettu muisti
Voit nähdä, miten web-työntekijä toimii käyttämättä jaettua muistia luo työntekijäkierre ja siirtää sille joitakin tietoja.
index.html
tiedostossa on pääskripti sisällä tunniste, kuten näet alla:
const w = uusi työntekijä ('worker.js'); var n = 9; w.postMessage (n);
worker.js
tiedosto sisältää työntekijän käsikirjoitus:
onmessage = (e) => console.group ('[työntekijä]'); console.log ('Pääkierteestä saadut tiedot:% i', e.data); console.groupEnd ();
Yllä olevan koodin avulla saamme seuraavan ulostulo konsolissa:
[työntekijä] Pääkierteestä saadut tiedot: 9
Voit lukea yllämainitun viestin web-työntekijöistä yllä olevien katkelmien täydellisen koodin selityksen vuoksi.
Pidä nyt mielessä, että tiedot ovat lähetetty kierteiden välillä käyttämällä postMessage ()
menetelmä. Tiedot ovat vastaanotti toisella puolella viesti
tapahtumakäsittelijä, tapahtuman arvona data
omaisuus.
Nyt, jos me muuttaa tietoja näyttääkö se päivitettynä vastaanottopäässä? Katsotaan:
const w = uusi työntekijä ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Kuten odotettiin, tietoja on ei päivitetty:
[työntekijä] Pääkierteestä saadut tiedot: 9
Miksi se olisi joka tapauksessa? Sen vain klooni, joka lähetetään työntekijälle pääskriptistä.
Web-työntekijät kanssa jaettu muisti
Nyt, me Käytä SharedArrayBuffer
esine samassa esimerkissä. Voimme luoda uuden SharedArrayBuffer
esimerkiksi käyttämällä Uusi
avainsana. Rakentaja ottaa yhden parametrin; pituusarvo tavuina, määritetään puskurin koko.
const w = uusi työntekijä ('worker.js'); buff = new SharedArrayBuffer (1); var arr = uusi Int8Array (buff); / * asetustiedot * / arr [0] = 9; / * puskurin (kopion) lähettäminen työntekijälle * / w.postMessage (buff);
Huomaa, että a SharedArrayBuffer
esine edustaa vain jaettua muistia. jotta nähdä ja muuttaa binääritietoja, meidän on käytettävä asianmukaista tietorakennetta (a TypedArray
tai a DataView
esine).
Vuonna index.html
tiedosto edellä, uusi SharedArrayBuffer
on luotu, vain yhden tavun pituinen. Sitten uusi Int8Array
, joka on yksi tyyppi TypedArray
esineitä asettaa tiedot “9” annetussa tavutilassa.
onmessage = (e) => var arr = uusi Int8Array (e.data); console.group ( '[työntekijä]'); console.log ('Pääkierteestä vastaanotetut tiedot:% i', arr [0]); console.groupEnd ();
Int8Array
käytetään myös työntekijässä tarkastella puskurissa olevia tietoja.
odotettu arvo näkyy konsolissa työntekijän langasta, mikä on juuri sitä, mitä halusimme:
[työntekijä] Pääkierteestä saadut tiedot: 9
Nyt, nyt päivitä pääkierteen tiedot nähdä, näkyykö muutos työntekijässä.
const w = new Worker ('worker.js'), buff = uusi SharedArrayBuffer (1); var arr = uusi Int8Array (buff); / * asetustiedot * / arr [0] = 9; / * puskurin (kopion) lähettäminen työntekijälle * / w.postMessage (buff); / * tietojen muuttaminen * / arr [0] = 1;
Ja kuten alla näet, päivitys ei heijasta työntekijän sisällä!
[työntekijä] Pääkierteeltä saadut tiedot: 1
Mutta koodi on myös on toimittava toisin päin: kun työntekijän arvo muuttuu aluksi, se myös päivitettävä kun se on painettu pääkierteestä.
Tässä tapauksessa koodi näyttää tältä:
onmessage = (e) => var arr = uusi Int8Array (e.data); console.group ( '[työntekijä]'); console.log ('Pääkierteestä vastaanotetut tiedot:% i', arr [0]); console.groupEnd (); / * tietojen muuttaminen * / arr [0] = 7; / * lähettäminen pääkierteeseen * / postMessage (");
tietoja muutetaan työntekijässä ja tyhjä viesti lähetetään pääkierteelle merkitsee, että puskurissa olevat tiedot on muutettu ja että se on valmis päälangan tulostamiseen.
const w = new Worker ('worker.js'), buff = uusi SharedArrayBuffer (1); var arr = uusi Int8Array (buff); / * asetustiedot * / arr [0] = 9; / * puskurin (kopion) lähettäminen työntekijälle * / w.postMessage (buff); / * tietojen muuttaminen * / arr [0] = 1; / * tulostetaan tiedot sen jälkeen, kun työntekijä on muuttanut sitä * / w.onmessage = (e) => console.group ('[main]'); console.log ('Päivitetyt tiedot, jotka on vastaanotettu työntekijän langasta:% i', arr [0]); console.groupEnd ();
Ja tämä toimii myös! Puskurin tiedot ovat samat kuin työntekijän sisällä olevat tiedot.
[työntekijä] Pääkierteeltä saadut tiedot: 1 [pää] Päivitetyt tiedot, jotka on saatu työntekijän langasta: 7
Arvo molemmissa tapauksissa päivitetään; sekä pää- että työntekijälangat tarkastelevat ja muuttavat samoja tietoja.
Lopulliset sanat
Kuten aiemmin mainitsin, jaetun muistin käyttäminen JavaScriptissä ei ole ilman haittapuolia. Kehittäjien on varmistettava, että suoritusjakso tapahtuu ennustetulla tavalla eikä mikään kierre ole kilpaillut saamaan samat tiedot, koska kukaan ei tiedä kuka ottaa pokaalin.
Jos olet kiinnostunut jaetusta muistista enemmän, tutustu dokumentaatioon Atomics
esine. Atomics-objekti voi auttaa sinua eräissä vaikeuksissa, vähentämällä jaetun muistin lukemisen / kirjoittamisen arvaamattomuutta.