Introduction à la mémoire partagée en JavaScript
La mémoire partagée est une fonctionnalité avancée de JavaScript, que les threads (parties d'un processus exécutées simultanément) peuvent exploiter. Partager la mémoire signifie ne pas avoir de mal à 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? Eh bien, presque. Dans cet article, nous verrons comment utiliser la mémoire partagée dans 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 des web workers pour créer des threads en JavaScript . L'API Web Workers permet de créer des threads de travail qui peuvent être utilisés pour exécuter du code en arrière-plan afin que le thread principal puisse continuer son exécution, traitant éventuellement des événements de l'interface utilisateur, sans aucune interruption de l'interface utilisateur.
Les threads de travail s'exécutent simultanément avec le thread principal et entre eux . Une telle 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 thread obtient les ressources nécessaires et communique les uns avec les autres en temps opportun est une tâche en soi, où une mésaventure peut aboutir à un résultat surprenant. Ou, si un thread change des données et qu'un autre le lit en même temps, que pensez-vous que l'autre thread verra? Les mises à jour ou les anciennes données?
Cependant, les web workers ne sont pas si faciles à bousiller. Lors de leur communication via l'utilisation de messages, les données qu'ils se transmettent ne sont pas originales mais une copie, ce qui signifie qu'ils ne partagent pas les mêmes données. Ils transmettent des copies de données les uns aux autres en cas de besoin.
Mais le partage est attentionné, et plusieurs threads peuvent aussi avoir besoin de regarder les mêmes données en même temps et de les changer. Donc, interdire le partage est un gros non-non . C'est là que l'objet SharedArrayBuffer
entre dans l'image. Cela nous permettra de partager des données binaires entre plusieurs threads .
L'objet SharedArrayBuffer
Au lieu de passer les copies de données entre les threads, nous passons des copies de l'objet SharedArrayBuffer
. Un objet SharedArrayBuffer
pointe vers la mémoire où les données sont enregistrées .
Ainsi, même lorsque les copies de SharedArrayBuffer
sont passées entre threads, elles pointent toutes vers la même mémoire où les données d'origine sont sauvegardées. Les threads peuvent ainsi visualiser et mettre à jour les données dans cette même mémoire .
Pour voir comment fonctionne un travailleur Web sans utiliser la mémoire partagée, nous créons un thread de travail et lui transmettons des données .
Le fichier index.html
contient le script principal dans un tag, comme vous pouvez le voir ci-dessous:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n);
Le fichier worker.js
porte le script worker :
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 la sortie suivante dans la console :
[worker] Données reçues du thread principal: 9
Vous pouvez lire mon article mentionné ci-dessus sur les travailleurs Web pour l'explication complète du code des extraits ci-dessus.
Pour l'instant, gardez à l'esprit que les données sont envoyées entre les threads en utilisant la méthode postMessage()
. Les données sont reçues de l'autre côté par le gestionnaire d'événements de message
, en tant que valeur de la propriété de data
de l'événement.
Maintenant, si nous changeons les données apparaîtront-elles mises à jour à la réception? Voyons voir:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Comme prévu, les données n'ont pas été mises à jour :
[worker] Données reçues du thread principal: 9
Pourquoi serait-ce, de toute façon? C'est juste un clone envoyé au travailleur à partir du script principal .
Travailleurs Web avec mémoire partagée
Maintenant, nous allons utiliser l'objet SharedArrayBuffer
dans le même exemple. Nous pouvons créer une nouvelle instance de SharedArrayBuffer
en utilisant le new
mot-clé . Le constructeur prend un paramètre; une valeur de longueur en octets, en spécifiant la taille du tampon.
const w = new Worker ('worker.js'); buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * réglage des données * / arr [0] = 9; / * envoi du tampon (copie) au worker * / w.postMessage (buff);
Notez qu'un objet SharedArrayBuffer
représente uniquement une zone de mémoire partagée . Pour voir et modifier les données binaires, nous devons utiliser une structure de données appropriée (un TypedArray
ou un objet DataView
).
Dans le fichier index.html
ci-dessus, un nouveau SharedArrayBuffer
est créé, avec une longueur d'un octet seulement. Ensuite, un nouvel Int8Array
, qui est un type d'objets TypedArray
, est utilisé pour définir les données sur "9" dans l'espace d'octets fourni .
onmessage = (e) => {var arr = nouveau Int8Array (e.data); console.group ('[worker]'); console.log ('Données reçues du thread principal:% i', arr [0]); console.groupEnd (); }
Int8Array
est également utilisé dans le worker pour visualiser les données dans le buffer .
La valeur attendue apparaît dans la console à partir du thread de travail, ce qui est exactement ce que nous voulions:
[worker] Données reçues du thread principal: 9
Maintenant, mettons à jour les données dans le thread principal pour voir si la modification est reflétée dans le travailleur.
const w = new Travailleur ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * réglage des données * / arr [0] = 9; / * envoi du tampon (copie) au worker * / w.postMessage (buff); / * modification des données * / arr [0] = 1;
Et, comme vous pouvez le voir ci-dessous, la mise à jour reflète dans le travailleur !
[worker] Données reçues du thread principal: 1
Mais le code doit également fonctionner dans l'autre sens : lorsque la valeur dans le worker change au début, elle doit également être mise à jour lorsqu'elle est imprimée à partir du thread principal.
Dans ce cas, notre code ressemble à ceci:
onmessage = (e) => {var arr = nouveau Int8Array (e.data); console.group ('[worker]'); console.log ('Données reçues du thread principal:% i', arr [0]); console.groupEnd (); / * modification des données * / arr [0] = 7; / * publication dans le thread principal * / postMessage (''); }
Les données sont modifiées dans le worker et un message vide est posté dans le thread principal pour signaler que les données dans le buffer ont été changées et sont prêtes pour le thread principal à sortir.
const w = new Travailleur ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * réglage des données * / arr [0] = 9; / * envoi du tampon (copie) au worker * / w.postMessage (buff); / * modification des données * / arr [0] = 1; / * impression des données après que le worker l'a changé * / w.onmessage = (e) => {console.group ('[main]'); console.log ('Données mises à jour reçues du thread de travail:% i', arr [0]); console.groupEnd (); }
Et, cela fonctionne aussi! Les données dans le tampon sont les mêmes que les données dans le worker.
[worker] Données reçues du thread principal: 1 [main] Données mises à jour reçues du thread de travail: 7
La valeur apparaît mise à jour dans les deux cas ; Les threads principal et de travail affichent et modifient les mêmes données.
Derniers mots
Comme je l'ai mentionné plus tôt, l'utilisation de la mémoire partagée en JavaScript n'est pas sans inconvénients . Il appartient aux développeurs de s'assurer que la séquence d'exécution se déroule comme prévu et qu'il n'y a pas deux threads qui courent pour obtenir les mêmes données car personne ne sait qui prendra le trophée.
Si vous souhaitez plus de mémoire partagée, consultez la documentation de l'objet Atomics
. L' objet Atomics peut vous aider avec certaines des difficultés, en réduisant la nature imprévisible de la lecture / écriture de la mémoire partagée.
5 guerres de campagne publicitaires massives entre les marques rivales
Aussi longtemps que nous pouvons nous en souvenir, les marques rivales se sont affrontées à travers un large éventail de supports publicitaires - des affiches et des publicités sur les panneaux publicitaires aux vidéos et aux courriels. Mais au moment où nous pensons qu'il n'y aura personne pour apporter quelque chose de nouveau à la table, certaines marques ont décidé d'intensifier leur jeu et d'utiliser des stratégies de publicité comparative pour se moquer ouvertement de leurs rivaux en créant des publicités parodiques.Les stratégi
20 annonces créatives qui vous donnent envie d'attendre l'ascenseur
Les publicités à travers les médias et les bannières deviennent trop courantes pour que les gens s'habituent à ignorer ces publicités et les évitent parfois activement . Tant de choses sont dépensées en publicité que le fait de ne pas attirer l'attention du bypassiste est simplement un indice que la technique utilisée n'est pas assez bonne.Des pannea