Homepage » Coding » Introduzione alla memoria condivisa in JavaScript

    Introduzione alla memoria condivisa in JavaScript

    Memoria condivisa è una funzionalità avanzata di JavaScript, che consente di sfruttare i thread (parti di un processo eseguite contemporaneamente). Condividere i mezzi di memoria non avendo il problema di passare i dati aggiornati tra i thread e tutti i thread possono accedere e aggiornare gli stessi dati nella memoria condivisa.

    Non suona adorabile? Be 'quasi. In questo post, vedremo come utilizzare la memoria condivisa in JavaScript e come decidere se questo è ciò che vuoi veramente fare.

    Vantaggi e svantaggi della memoria condivisa

    Noi usiamo lavoratori del web a creare discussioni in JavaScript. L'API Web Workers ci consente di creare thread di lavoro che possono essere utilizzati eseguire codice in background in modo che il thread principale sia libero di continuare la sua esecuzione, eventualmente elaborando gli eventi dell'interfaccia utente, assicurando il blocco dell'interfaccia utente.

    Discussioni del lavoratore eseguire contemporaneamente il thread principale e l'altro. Tale esecuzione simultanea di parti diverse di un'attività è rapida. Finisci più velocemente, ma ha anche una serie di problemi.

    Assicurarsi che ogni thread ottiene le risorse necessarie e comunica tra loro in modo tempestivo è un compito in sé, in cui un contrattempo può portare a un risultato sorprendente. O se un thread sta cambiando i dati e un altro lo sta leggendo allo stesso tempo, cosa pensi che l'altro thread vedrà? I dati aggiornati o vecchi?

    Tuttavia, i web worker non sono così facili da rovinare. Durante la loro comunicazione tramite l'uso di messaggi, i dati che si inviano l'un l'altro è non originale ma una copia, il che significa che non lo fanno Condividere gli stessi dati. Essi passare copie di dati tra loro quando ce n'è bisogno.

    Ma la condivisione è importante, e più thread potrebbero anche dover guardare gli stessi dati nello stesso momento e cambiarli. Così, vietare la condivisione è un grande no-no. Questo è dove il SharedArrayBuffer l'oggetto entra nell'immagine. Ci lascerà condividi dati binari tra più thread.

    Il SharedArrayBuffer oggetto

    Invece di passare le copie dei dati tra i thread, noi passare copie del SharedArrayBuffer oggetto. UN SharedArrayBuffer oggetto punta alla memoria in cui i dati vengono salvati.

    Quindi, anche quando le copie di SharedArrayBuffer sono passati tra i fili, loro tutto punterà ancora alla stessa memoria dove vengono salvati i dati originali. I fili, quindi, possono visualizzare e aggiornare i dati nella stessa memoria.

    Operatori Web senza memoria condivisa

    Per vedere come funziona un web worker senza usare la memoria condivisa, noi creare un thread di lavoro e passare alcuni dati ad esso.

    Il index.html il file contiene il script principale dentro a tag, come puoi vedere qui sotto:

     const w = new Worker ('worker.js'); var n = 9; w.postMessage (n); 

    Il worker.js il file contiene il script di lavoro:

     onmessage = (e) => console.group ('[worker]'); console.log ('Dati ricevuti dal thread principale:% i', e.data); console.groupEnd ();  

    Usando il codice sopra, otteniamo quanto segue uscita nella console:

     [worker] Dati ricevuti dal thread principale: 9 

    Puoi leggere il mio post sopra riportato sui web worker per la spiegazione completa del codice dei frammenti di cui sopra.

    Per ora, tieni presente che i dati lo sono inviato avanti e indietro tra i thread usando il postMessage () metodo. I dati sono ricevuto dall'altra parte dal Messaggio gestore di eventi, come valore dell'evento dati proprietà.

    Ora, se noi cambia i dati apparirà aggiornato alla fine ricevente? Vediamo:

     const w = new Worker ('worker.js'); var n = 9; w.postMessage (n); n = 1; 

    Come previsto, il dati ha non stato aggiornato:

     [worker] Dati ricevuti dal thread principale: 9 

    Perché dovrebbe essere, comunque? Suo solo un clone inviato al lavoratore dallo script principale.

    Operatori Web con memoria condivisa

    Ora, lo faremo utilizzare il SharedArrayBuffer oggetto nello stesso esempio. Possiamo creare un nuovo SharedArrayBuffer istanza di usando il nuovo parola chiave. Il costruttore prende un parametro; un valore di lunghezza in byte, specificando la dimensione del buffer.

     const w = new Worker ('worker.js'); buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * dati di impostazione * / arr [0] = 9; / * invio del buffer (copia) a worker * / w.postMessage (buff); 

    Si noti che a SharedArrayBuffer oggetto rappresenta solo un'area di memoria condivisa. A vedere e modificare i dati binari, abbiamo bisogno di utilizzare una struttura dati appropriata (a TypedArray o a DataView oggetto).

    Nel index.html file sopra, un nuovo SharedArrayBuffer viene creato, con una lunghezza di un solo byte. Quindi, un nuovo Int8Array, che è un tipo di TypedArray oggetti, è abituato a imposta i dati su “9” nello spazio byte fornito.

     onmessage = (e) => var arr = new Int8Array (e.data); console.group ( '[lavoratore]'); console.log ('Dati ricevuti dal thread principale:% i', arr [0]); console.groupEnd ();  

    Int8Array è anche usato nel lavoratore, per guarda i dati nel buffer.

    Il il valore previsto appare nella console dal thread di lavoro, che è esattamente quello che volevamo:

     [worker] Dati ricevuti dal thread principale: 9 

    Ora facciamo aggiorna i dati nel thread principale per vedere se il cambiamento si riflette nel lavoratore.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * dati di impostazione * / arr [0] = 9; / * invio del buffer (copia) a worker * / w.postMessage (buff); / * modifica dei dati * / arr [0] = 1;

    E, come puoi vedere sotto, l'aggiornamento riflette all'interno del lavoratore!

     [worker] Dati ricevuti dal thread principale: 1 

    Ma anche il codice ha bisogno di lavorare al contrario: quando il valore nel lavoratore cambia all'inizio, ha anche bisogno di essere aggiornato quando è stampato dal thread principale.

    In questo caso, il nostro codice è simile al seguente:

     onmessage = (e) => var arr = new Int8Array (e.data); console.group ( '[lavoratore]'); console.log ('Dati ricevuti dal thread principale:% i', arr [0]); console.groupEnd (); / * cambiando i dati * / arr [0] = 7; / * pubblicazione sul thread principale * / postMessage ("); 

    Il i dati sono cambiati nel lavoratore e un il messaggio vuoto è pubblicato nella discussione principale segnalando che i dati nel buffer sono stati modificati ed è pronto per l'emissione del thread principale.

     const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * dati di impostazione * / arr [0] = 9; / * invio del buffer (copia) a worker * / w.postMessage (buff); / * modifica dei dati * / arr [0] = 1; / * stampa i dati dopo che il lavoratore lo ha cambiato * / w.onmessage = (e) => console.group ('[main]'); console.log ('Dati aggiornati ricevuti da thread worker:% i', arr [0]); console.groupEnd ();  

    E anche questo funziona! I dati nel buffer sono gli stessi dei dati all'interno dell'operatore.

     [worker] Dati ricevuti dal thread principale: 1 [main] Dati aggiornati ricevuti dal thread worker: 7 

    Il valore appare aggiornato in entrambi i casi; entrambi i thread principale e di lavoro stanno visualizzando e modificando gli stessi dati.

    Parole finali

    Come ho detto prima, usando la memoria condivisa in JavaScript non è senza lati negativi. Spetta agli sviluppatori assicurarsi che il la sequenza di esecuzione avviene come previsto e non ci sono due discussioni in corsa per ottenere gli stessi dati perché nessuno sa chi prenderà il trofeo.

    Se sei interessato alla memoria condivisa di più, dai un'occhiata alla documentazione di Atomics oggetto. Il L'oggetto atomico può aiutarti ad affrontare alcune delle difficoltà, riducendo la natura imprevedibile della lettura / scrittura dalla memoria condivisa.