Introduction à la mémoire partagée en JavaScript
La memoire partagée est une fonctionnalité avancée de JavaScript que les threads (parties d’un processus exécutées simultanément) peuvent exploiter. Partager les moyens de la mémoire ne pas avoir la peine de transmettre des données mises à jour entre les threads et tous les threads peuvent accéder et mettre à jour les mêmes données dans la mémoire partagée.
Cela ne semble-t-il pas charmant? Enfin presque. Dans ce post, nous verrons comment utiliser la mémoire partagée en JavaScript et comment décider si c'est ce que vous voulez vraiment faire.
Avantages et inconvénients de la mémoire partagée
Nous utilisons travailleurs Web à créer des discussions en JavaScript. L’API Web Workers nous permet de créer des threads de travail pouvant être utilisés pour exécuter du code en arrière-plan de sorte que le thread principal soit libre de continuer son exécution, en traitant éventuellement les événements d'interface utilisateur, en veillant à ce que l'interface utilisateur ne soit pas gelée.
Fils de travailleur courir en même temps que le fil principal et l'autre. Cette exécution simultanée de différentes parties d’une tâche permet de gagner du temps. Vous finissez plus vite, mais il a aussi ses propres problèmes.
S'assurer que chaque fil obtient les ressources nécessaires et communique les uns avec les autres en temps opportun est une tâche en soi, où un incident peut avoir un résultat surprenant. Ou si un fil change des données et un autre le lit en même temps, que pensez-vous que l'autre fil verra? Les données mises à jour ou anciennes?
Cependant, les travailleurs Web ne sont pas si faciles à gâcher. Lors de la communication via l’utilisation de messages, les données qu’ils s’envoient sont pas l'original mais une copie, ce qui signifie qu'ils ne le font pas partager les mêmes données. Ils passer des copies de données les uns aux autres si nécessaire.
Mais partager, c'est bienveillant et plusieurs threads peuvent aussi avoir besoin d'examiner les mêmes données en même temps et de les modifier. Alors, interdire le partage est un gros non-non. C'est là que le SharedArrayBuffer
l'objet entre en scène. Il nous laissera partager des données binaires entre plusieurs threads.
le SharedArrayBuffer
objet
Au lieu de passer les copies de données entre les threads, nous transmettre des copies du SharedArrayBuffer
objet. UNE SharedArrayBuffer
objet pointe vers la mémoire où les données sont sauvegardées.
Ainsi, même lorsque les copies de SharedArrayBuffer
sont passés entre les threads, ils tous vont toujours pointer vers la même mémoire où les données d'origine sont enregistrées. Les fils peuvent donc visualiser et mettre à jour les données dans la même mémoire.
Travailleurs Web sans pour autant la memoire partagée
Pour voir comment un travailleur Web fonctionne sans utiliser de mémoire partagée, nous créer un thread de travail et lui transmettre des données.
le index.html
le dossier contient le scénario principal à l'intérieur d'un tag, comme vous pouvez le voir ci-dessous:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n);
le worker.js
le fichier porte le script de travailleur:
onmessage = (e) => console.group ('[worker]'); console.log ('Données reçues du thread principal:% i', e.data); console.groupEnd ();
En utilisant le code ci-dessus, nous obtenons ce qui suit sortie dans la console:
[travailleur] Données reçues du thread principal: 9
Vous pouvez lire mon article susmentionné sur les travailleurs Web pour une explication complète du code des extraits ci-dessus..
Pour l'instant, gardez à l'esprit que les données sont envoyé en arrière entre les discussions en utilisant le postMessage ()
méthode. Les données sont reçu de l'autre côté par le message
gestionnaire d'événements, comme la valeur de l'événement Les données
propriété.
Maintenant, si nous changer les données apparaîtra-t-il mis à jour à la réception? Voyons voir:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Comme prévu, le les données ont ne pas été mis à jour:
[travailleur] Données reçues du thread principal: 9
Pourquoi serait-ce, de toute façon? Ses juste un clone envoyé au travailleur à partir du script principal.
Travailleurs Web avec la memoire partagée
Maintenant, nous allons Utilisez le SharedArrayBuffer
objet dans le même exemple. Nous pouvons créer un nouveau SharedArrayBuffer
exemple par en utilisant le Nouveau
mot-clé. Le constructeur prend un paramètre; une valeur de longueur en octets, spécifiant la taille du tampon.
const w = new Worker ('worker.js'); buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * Données de réglage * / arr [0] = 9; / * envoi du tampon (copie) au travailleur * / w.postMessage (buff);
Notez que SharedArrayBuffer
objet représente seulement une zone de mémoire partagée. À voir et changer les données binaires, nous devons utiliser une structure de données appropriée (un TypedArray
ou un DataView
objet).
dans le index.html
fichier ci-dessus, un nouveau SharedArrayBuffer
est créé avec une longueur d'un octet seulement. Ensuite, un nouveau Int8Array
, qui est un type de TypedArray
objets, est utilisé pour régler les données sur “9” dans l'espace octet fourni.
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[travailleur]'); console.log ('Données reçues du thread principal:% i', arr [0]); console.groupEnd ();
Int8Array
est également utilisé chez le travailleur, pour voir les données dans le tampon.
le la valeur attendue apparaît dans la console du thread de travail, ce qui est exactement ce que nous voulions:
[travailleur] Données reçues du thread principal: 9
Maintenant mettre à jour les données dans le fil principal pour voir si le changement se reflète dans le travailleur.
const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * Données de réglage * / arr [0] = 9; / * envoi du tampon (copie) au travailleur * / w.postMessage (buff); / * modification des données * / arr [0] = 1;
Et, comme vous pouvez le voir ci-dessous, la mise à jour réfléchit à l'intérieur du travailleur!
[travailleur] Données reçues du thread principal: 1
Mais, le code aussi doit travailler dans l'autre sens: quand la valeur dans le worker change au début, ça doit également être mis à jour quand il est imprimé à partir du fil principal.
Dans ce cas, notre code ressemble à ceci:
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[travailleur]'); console.log ('Données reçues du thread principal:% i', arr [0]); console.groupEnd (); / * modification des données * / arr [0] = 7; / * publication sur le fil principal * / postMessage (");
le les données sont modifiées dans le travailleur Et un un message vide est posté sur le fil principal signalant que les données dans la mémoire tampon ont été modifiées et sont prêtes pour la sortie du thread principal.
const w = new Worker ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * Données de réglage * / arr [0] = 9; / * envoi du tampon (copie) au travailleur * / w.postMessage (buff); / * modification des données * / arr [0] = 1; / * imprimer les données après que le travailleur les ait modifiées * / w.onmessage = (e) => console.group ('[principal]'); console.log ('Données mises à jour reçues du thread de travail:% i', arr [0]); console.groupEnd ();
Et ça marche aussi! Les données dans le tampon sont les mêmes que les données à l'intérieur du travailleur.
[travailleur] Données reçues du thread principal: 1 [main] Données mises à jour reçues du thread de travail: 7
La valeur semble mis à jour dans les deux cas; les threads principaux et de travail affichent et modifient les mêmes données.
Mots finaux
Comme je l'ai mentionné précédemment, utiliser la mémoire partagée en JavaScript n'est pas sans inconvénients. Il appartient aux développeurs de s’assurer que le séquence d'exécution se passe comme prévu et il n'y a pas deux fils en compétition pour obtenir les mêmes données car personne ne sait qui remportera le trophée.
Si la mémoire partagée vous intéresse davantage, consultez la documentation de la L'atomique
objet. le Atomics object peut vous aider avec certaines des difficultés, en réduisant le caractère imprévisible de la lecture / écriture à partir de la mémoire partagée.