Skip to content

Latest commit

 

History

History
120 lines (79 loc) · 8.62 KB

5-event-loop.md

File metadata and controls

120 lines (79 loc) · 8.62 KB

🐢 Node.js

🎡 Event-loop

Logo de libuv

Introduction

Quand vous souhaitez devenir meilleur en Node.js il est impératif de comprendre comment l’event-loop (fourni par le projet libuv) fonctionne et réagit pour notamment:

  • Mieux comprendre la logique et l'ordre d'exécution de votre code.
  • Optimiser et garantir les performances de votre application.
  • Tout simplement approfondir vos connaissances sur votre stack technique.

Petit challenge, pouvez-vous deviner l’ordre des logs ?

async function a(val) {
    console.log("A", val);
}
setImmediate(() => console.log("B"));

new Promise((res) => {
    for (let id = 0; id < 1e9; id++) {}
    setImmediate(() => console.log("C"));
    process.nextTick(() => res("D"));
    console.log("E");
}).then(console.log);

queueMicrotask(() => console.log("F"));
(async(res) => {
    for (let id = 0; nid < 1e6; id++) {}
    process.nextTick(() => console.log("G"));
    return "H";
})().then(console.log);

process.nextTick(() => console.log("I"));
const promises = [];
let n = 0;
for (; n < 10; n++) promises.push(a(n));

console.lgo("J");
Promise.all(promises);

Reactor pattern

Quand il est question d’events-loop on parle souvent de Reactor pattern depuis 1996 (c'est le principe qui définit les fondamentaux et qui pourra notamment vous permettre de comprendre d’autres pattern de concurrence comme Proactor).

Dans le cadre d’une Event-loop/Reactor on parlera souvent aussi d'algorithme Round-robin et Demultiplexing d'évènements.

Schéma simple d’un Reactor (events loop).

reactor event loop

Le réacteur prend en input un évènement (lire un fichier, envoyer un paquet sur le réseau) qui aura un cycle de vie prédéfini au sein de la loop en fonction de sa nature (et de l’implémentation). Les I/O bloquant seront, la plupart du temps, gérés au sein d’abstractions bas niveau fournies par le système comme epoll, kqueue et event ports (tout dépend du système d’exploitation cible). Quand il n’est pas possible d’utiliser les ressources du système, des threads seront bien souvent créés.

Une fois le traitement terminé le réacteur s’occupera de déclencher le callback lié à l’évènement pour signaler que le traitement est terminé (avec succès ou en erreur). Je parle ici de callback pour rester bas niveau, mais il peut s’agir d’une Promise/Future ou de toute autre structure ayant pour objectif de gérer la résolution d’un événement Asynchrone.

Lien bonus pour les motivés: EN Reactor - An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events

🎥 Un peu d’histoire

event loop history

La notion d'event, event-driven et event-loop ne date pas d’hier et les premières apparitions date des années 80 (même si le pattern est devenu fort populaire depuis une dizaine d’années grâce à l’apparition de lib comme Libuv ou plus récemment Tokio sur Rust).

Il existe très probablement des librairies équivalentes ou des implémentations très sérieuses sur les différents runtime (Python, Ruby, PHP, Lua, Perl etc). Le langage de programmation Julia est d’ailleurs basé sur Libuv.

Aujourd’hui il devient très clair que le pattern a fait ses preuves et qu’il est très largement apprécié par les développeurs du monde entier pour construire des programmes concurrents (même s’il faut toujours garder en tête qu’il y aura toujours des points forts ainsi que des points faibles).

Il n’est donc ici pas uniquement question de devenir meilleur en Node.js ou en JavaScript, mais d’acquérir des compétences et des notions qui vous seront utiles tout au long de votre carrière.

Libuv

Libuv est donc la librairie qui est utilisée dans Node.js pour l’event-loop. Son fonctionnement ne vous impacte pas directement dans votre code (elle est transparente pour les développeurs… c’est l’objectif de Node.js ^^).

Il est important de comprendre comment elle fonctionne a minima car l’exécution des différentes phases va définir comment votre code fonctionnera et dans quel ordre il sera exécuté (ce qui vous permettra de résoudre le challenge de l’introduction).

Le schéma ci-dessous est un schéma que j’ai construit pour représenter les différentes phases de l’event-loop (vous noterez la claire séparation entre votre code, la loop et le système d’exploitation).

event loop phase

Sur le sujet je vous recommande d’aller lire en premier lieu les pages suivantes :

📜 Articles et talks

Node.js event-loop par moi (version HD ici).

Libuv event loop phases

Divers articles de vulgarisation. Ils peuvent vous permettre de mieux comprendre divers sujets vus plus haut d’une façon plus abordable :

Divers talks sur Node.js et libuv (les deux derniers sont en français) :


⬅️ 🐢 Node.js: 📰 Conférences et Articles | ➡️ 🐢 Node.js: 👽 Native API (création d’addon natif en C, C++ et Rust)