25 Jun

Rebuilding Node's Event Loop

This post is based on a guest post I wrote on DailyJS.

The Heart of the Node Event Loop

I am a big believer in mastering your tools to become a better developer. And the best way to master your tools is to understand how they are made.

Do you know what’s happening inside Node.js or EventMachine?

There’s an event loop. So there must be a loop somewhere, right? A loop handling events. Let’s take a look…

The Loop

Event loops like the one in Node or EventMachine are designed to react to I/O events. This could be an incoming connection, data arriving on a socket, etc. What’s more, it must react to these events extremely quickly. Like most things in software, the simplest design is usually the fastest. And event loops are usually very simple.

First, it consists of an endless loop:

while (true) {
  ...
}

Everything will happen in that loop. All of your Node programs will be running inside that loop. Which is similar to the loop you’ll find in virtual machines and emulators, where an actual processor is simulated instead.

A Turn in the Loop

Somewhere in the loop, your process will wait for I/O events to happen. Luckily, most operating systems come with a function that allows us to do just that. Several options exist, such as kqueue on Mac OS, epoll on Linux. The most portable (but slowest) one is select. For more on this, see select.

select watches a bunch of I/O objects (files, sockets) and lets you know when something happens. It looks something like this:

while (true) { // That's our loop
  var events = select(<I/O objects to watch>)
}

React

At this point in the loop, we know an event has occurred. We must react to those events. In Node and many other event-based systems, this is done via callbacks.

In your Node program, you’ll define callbacks like so:

object.on('read', function() { ... })

This will register the callback inside the event loop, so that it knows what to do when this event happens. Introducing that in our loop, we’ll end up with the following:

while (true) {
  var events = select(<I/O objects to watch>)
  
  events.forEach(function(event) {
    var callback = findCallbackForEvent(event)
    callback() // This calls the callback function
  });
}

After we’re done executing all of the callbacks, we’re ready for another turn in the loop – it’ll patiently wait for other I/O events to happen.

But There’s More!

This is a simplification of how things work internally. However, even if the Node event loop is a little more complex than that, the structure is the same. It’s still a loop using select (or a variation), and triggering callbacks.

Still not sure how this allows huge amounts of concurrent connections to be handled by a server? Or you’d like to dive deeper into event loops and how it works in Node, and how other features such as setTimeout are implemented? Join the next edition of my online class.

Everything is online. You can ask questions. You’ll get exercises. And you’ll also get recordings of the class to watch again at your leisure.

The class already helped a number of developers master Node and EventMachine. Here’s what one of them had to say:

I don’t know where to begin. I am blown away. Other online “classes” that I have attended are very lackluster compared to your class.
The format was amazing, […], building on top of each lesson as we progressed.
[…]
I am not sure it could have been done better. This is complicated stuff, and I feel you have gone well above expectations to help understand the event loop.
I can easily say that I have leveled up – it has changed my thinking on event driven programs. Not just in Node but for Ruby as well.
- Tom Buchok

The previous edition was a great success and sold out quickly. I’m expecting this one to sold out very soon too. So if you’re interested, book now!

Like what you just read? Subscribe to my newsletter to learn how I make a living selling my products online.

Or if you're into coding, join my free class on rebuilding a Ruby web server.

blog comments powered by Disqus