What logical flow model is used for event loop in Nodejs (Google Chrome)

Viewed 266

For a long time I thought that event loop implementation (libuv?) used in Chrome and Node.js used threads. But then I was reading this article on lightweight threads in Java that stated the following:

...instead of creating threads for each concurrent task (and blocking tasks), a dedicated thread (called an event loop) looks through all the tasks that are assigned to threads in a non-reactive model, and processes each of them on the same CPU core.

And the the book Computer Systems. A Programmer’s Perspective in the chapter on concurrent applications states that modern operating systems provide three basic approaches for building concurrent programs (3 approaches to implementing logic flows):

  • Processes. With this approach, each logical control flow is a process that is scheduled and maintained by the kernel. Since processes have separate virtual address spaces, flows that want to communicate with each other must use some kind of explicit interprocess communication (IPC) mechanism.

  • I/O multiplexing. This is a form of concurrent programming where applications explicitly schedule their own logical flows in the context of a single process. Logical flows are modeled as state machines that the main program explicitly transitions from state to state as a result of data arriving on file descriptors. Since the program is a single process, all flows share the same address space.

  • Threads. Threads are logical flows that run in the context of a single process and are scheduled by the kernel. You can think of threads as a hybrid of the other two approaches, scheduled by the kernel like process flows and sharing the same virtual address space like I/O multiplexing flows.

So now I'm wondering now if the event loop falls under I/O multiplexing logical flow and doesn't use threads?

1 Answers

I have nothing to do with V8 team, but I'll try to answer the question.

First of all, V8 itself has nothing to do with an event loop. Node.js uses libuv to implement the event loop plus abstractions for OS-specific APIs (network, FS, and so on). The event loop itself is run on a single OS thread and most of the network operations are executed on that thread based I/O multiplexing APIs (epoll, kqueue, etc.).

But libuv also has a thread pool to run blocking I/O (e.g. FS, DNS lookups) and CPU intensive operations (e.g. crypto). The thread pool is integrated (communicates) with the event loop through an in-memory queue. When a blocking/CPU intensive task has to be started it's put into the queue and later on one of the threads starts processing it.

So, Node.js uses a number of approaches to achieve concurrency among the user operations: OS threads (BTW this includes the worker_threads module), I/O multiplexing, multiple processes (with the child_process module).

V8 also uses a number of OS threads for its own purposes (say, GC), but it doesn't need to be aware of the event loop or provide any abstractions for the OS-level APIs. Its goal is to, well, execute the given JS code and provide a solid embedder API, so that you can build a browser/runtime with it.

Related