paint-brush
Comment le multi-traitement m'a aidé à accélérer mon application JavaScript par 4xpar@rusanov
2,829 lectures
2,829 lectures

Comment le multi-traitement m'a aidé à accélérer mon application JavaScript par 4x

par Dmitrii Rusanov5m2023/07/25
Read on Terminal Reader

Trop long; Pour lire

Nous approfondirons l'énigme du multitraitement dans Node.js, armés d'exemples de code captivants.
featured image - Comment le multi-traitement m'a aidé à accélérer mon application JavaScript par 4x
Dmitrii Rusanov HackerNoon profile picture
0-item
1-item

JavaScript a été intrinsèquement conçu comme une bête à un seul thread. Pourtant, sur les terrains sauvages de l'informatique, les prédateurs connus sous le nom de « multiprocesseurs » et « processeurs multicœurs » attendent d'être apprivoisés, prêts à accélérer l'exécution de votre code à des vitesses inouïes. 💪🚀


J'ai osé entrer dans cette jungle, j'ai soumis mon code au test de survie ultime et j'en suis ressorti avec des résultats étonnants. 🏆 Maintenant, c'est à votre tour de me rejoindre dans cette quête passionnante. Nous plongerons profondément dans l'énigme du multitraitement dans Node.js , armés d'exemples de code captivants et braquerons le flambeau 🔦 sur les fruits spectaculaires de mes expériences. 🍎🍏


Préparez-vous à embarquer dans cette aventure pleine d'adrénaline consistant à booster les performances de JavaScript grâce à la magie du multitraitement ! Bouclez votre ceinture et préparez-vous alors que nous sommes sur le point de nous lancer dans le domaine fascinant du codage à indice d'octane élevé.


Avant de nous aventurer trop loin, équipons-nous de quelques outils fiables. Nous allons créer quelques fonctions auxiliaires pour simuler le travail de calcul souvent ardu. Créons un nouvel artefact, un fichier nommé utils.js , et inscrivons-y ces incantations essentielles.


 // utils.js function generateRandomData(size) { const data = []; for (let i = 0; i < size; i++) { data.push(Math.random()); } return data; } function processData(data) { // performs some calculations on the array // to simulate high resource intensity let sum = 0; for (let num of data) { for (let j = 0; j < 1000000; j++) { sum += Math.sqrt(num); } } return sum; } module.exports = { generateRandomData, processData, };

Version monothread

L'exécution dans un seul thread représente une approche assidue et fiable de la résolution de problèmes. La version monothread du script peut être décrite visuellement comme telle. fil unique Le code de la version monothread est assez simple. Nous créons des données et les envoyons pour traitement.

 // sync.js const { generateRandomData, processData } = require("./utils"); const data = generateRandomData(30000); console.time("single-thread. Time:"); processData(data); console.timeEnd("single-thread. Time:");

On lance le script avec la commande : node sync.js

Nous attendons... et attendons... et attendons...

Plus la charge est longue, plus le café est fort ! Et après toute cette attente, nous recevons un message indiquant le temps d'exécution du script.


 single-thread. Time:: 25.888s


Cette approche convient à la plupart des cas. Mais il y a un hic. Qui, sain d'esprit, adore l'art d'attendre ? Pour surmonter ce retard angoissant, nous devons exploiter toute la puissance de feu de nos ordinateurs ! Après tout, la plupart des ordinateurs modernes sont équipés de plusieurs cœurs de processeur !


Alors, pourquoi devrions-nous laisser ces cœurs supplémentaires inactifs alors qu'ils pourraient traiter des chiffres et accélérer l'exécution de notre code ? Il est temps d'illuminer ces géants endormis et de libérer la puissance brute du multitraitement ! Plongeons-nous !

Version multi-traitée du script

En adoptant l'approche multiprocessus, nous pouvons tirer parti de plusieurs cœurs de notre CPU, propulsant les performances de notre script plusieurs fois. Le processus de fonctionnement de notre code multiprocessus peut être visualisé avec ce diagramme.

version multitraitement Essentiellement, nous partitionnons simplement un ensemble de données important en segments et attribuons chaque segment pour le traitement à un cœur de processeur discret.


Créez un fichier intitulé multi-process.js et remplissez-le avec le contenu suivant.


 // multi-process.js const childProcess = require("child_process"); const utils = require("./utils"); const data = utils.generateRandomData(30000); const chunkSize = Math.ceil(data.length / 4); const chunks = []; for (let i = 0; i < 4; i++) { const start = i * chunkSize; const end = start + chunkSize; chunks.push(data.slice(start, end)); } console.time("multiProcessed"); const workers = []; let results = []; // result collection array for (let i = 0; i < chunks.length; i++) { const worker = childProcess.fork("./worker.js"); // pass its number and data to the workflow worker.send({ workerNumber: i, data: chunks[i] }); workers.push( new Promise((resolve, reject) => { worker.on("message", (result) => { results.push(result); // add the result to the result array resolve(); }); worker.on("error", reject); worker.on("exit", (code) => { if (code !== 0) { reject(new Error(`Worker stopped with exit code ${code}`)); } }); }) ); } Promise.all(workers) .then(() => { console.timeEnd("multiProcessed"); console.log("Processing results:", results); }) .catch((err) => console.error(err));


Ce code révèle l'orchestration d'un processus de travail solitaire dans la symphonie de la gestion de données multi-traitées dans Node.js.


Bref, voici ce qui se passe :

  • Le travailleur reçoit les données et leur numéro du processus principal via process.on('message') .

  • La fonction processData effectue des calculs sur la portion de données affectée à ce travailleur.

  • Le résultat est renvoyé au processus principal via `process.send()``.

  • Le travailleur se termine avec le code 0 via process.exit() .


Lancez le script avec la commande : node multi-process.js

Tenez bon pour le turbo...

Chargement rapide Et nous obtenons la conclusion que le code a fonctionné en 5 secondes !

 Worker 0 started Worker 1 started Worker 2 started Worker 3 started ==================== Worker 1 finished ==================== Worker 2 finished ==================== Worker 3 finished ==================== Worker 0 finished multiProcessed: 5.266s Processing results: [ 4971422688.053512, 4989646323.157899, 4999088030.661542, 5008034869.924775 ]


Notre script a fonctionné quatre fois plus vite ! N'est-ce pas magnifique ?

Le grand dévoilement : résultats des tests

Avec une curiosité avide, j'ai exécuté les deux scripts sur un ordinateur doté d'un processeur à 4 cœurs, attendant de voir la magie se dérouler :


  • L'artiste solo, notre script à thread unique, a traité avec diligence les données en 25,8 secondes .

  • L'équipe puissante, notre script multi-thread, l'a fait sortir du parc en seulement 5,2 secondes !


Découvrez la puissance du multitraitement – plus que quadrupler la vitesse des calculs !

Ces contrastes frappants mettent en évidence la façon dont le multitraitement peut considérablement amplifier les capacités de calcul de votre machine et réduire le temps d'exécution.

Dernières pensées

Notre exploration passionnante brosse un tableau saisissant de la façon dont le multitraitement peut accélérer les tâches de calcul dans Node.js. Libérer votre code sur chaque cœur de processeur offre un bond tangible en termes de performances, semblable au passage de la marche à la téléportation !


Cela vaut vraiment la peine d'ajouter cette flèche à votre carquois de codage et d'expérimenter cette approche dans vos projets. Et avec l'avènement des Worker Threads dans Node.js, la mise en œuvre du multitraitement est devenue un jeu d'enfant.


Vous avez une montée d'adrénaline en lisant ceci ? N'hésitez pas à partager vos propres aventures avec le multitraitement dans Node.js dans les commentaires ci-dessous ! Continuons à percer ensemble les mystères du codage à grande vitesse.