TL;DR
NodeJS uses an event loop (essentially a while loop) to run concurrent processes, for a smooth experience. This design is due to JavaScript and DOM operations being single-threaded. While others languages typically use multi-threading instead to achieve concurrency.
This single-threaded approach scales well in certain cases like for non-blocking UI or when thousands of threads incurs a cost of switching threads.
UPDATE: I originally thought the single-threaded approach was a limitation of Node and JS which prevents scaling, but it can be strength (see comment discussion), so I've updated this article.
The origin of NodeJS and the need for concurrency
I heard that NodeJS was created because JavaScript was the only language with an event loop.
JavaScript (or ECMAScript) was built for the browser /then repurposed to run server-side scripts applications under the NodeNS runtime environment. And Node that was built on event-driven programming to allow asynchronous tasks. This means concurrent processing can handle non-blocking tasks smoothly -- such as to fetch data while rendering UI and also checking for mouse-based events to fire.
Node achieves this through what is known as the event loop. The concurrency page on the Mozilla docs has an Event Loop section which says that it is usually implemented using a while
loop which continously checks for events to fire.
The top of that page explains that this is not typical of concurrency other languages, like C or Java. These do not have the single-threaded limitation of JS and so use multi-threading instead of an event loop.
NodeJS and the event loop
In this talk by the Node creator, he explains in the first minute that the event loop (from the browser side) turned out to be necessary for the success of Node.
This is necessary because Node is single-threaded:
The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible.
And the reason Node is single-threaded is because JavaScript has to run in the browser as single-threaded -- since parallel operations on the DOM tree are not safe. See below.
Why then shouldn’t we just handle all the events we are subscribed to in old-fashioned parallel way? The reason is that we don’t want to change the DOM in parallel: this is because the DOM tree is not thread-safe and it would be a mess if we tried to do it. Because of this limitation, all our JavaScript code should be executed in single thread, while at the same time ensuring that it handles all the events and doesn’t lose any callback.
Follow the articles above for more detail on the event loop.
UPDATE: I found this series where the first article has some neat animations on the event loop - check it out.
More details on concurrency in other languages
Apache and Ruby using multiple threads but are inefficient at scale - see comment below.
Python has the threading library as well as multithreading library for multi-core processing.
Threading in Elixir is supposed to be a great strength for handling millions of requests efficiently.
New languages like Go and Rust can be very efficient at high-performance computing for modern computing tasks - in particular concurrent tasks that would be much slower in older languages.
Go was designed from the start to be fast to develop, fast and to handle concurrency with a "goroutine". See concurrency in the docs and an example of goroutines.
Top comments (7)
Mate, this is plain wrong:
You need to research more. Here is Wikipedia for example:
en.m.wikipedia.org/wiki/Node.js
Ryan wanted non blocking I/O thus he selected the language which had the event loop - the JavaScript.
See his talk when he complains about Ruby, great language but awful blocking runtime.
My apologies. I am drawing on what I find and my knowledge is limited in this area. I can't find the reference now but the source I found talked about alternatives being instigated for event loop and then event loop selected.
Fair enough that Apache and Ruby handle things poorly in this regard. I saw something about the cost of maintaining many threads increasing at scale.
Though Apache is mostly replaced by Nginx and Ruby is in decline from what I heard.
Still, languages like C and Java that are known for their speed use multi-threading to be non-blocking rather than an event loop, and Exilir's multi threading scales amazingly from talking to an Elixir dev. So Event Loop may handle things differently in a single thread but I don't see how Event Loop is a necessity (I don't know of other languages that use it, certainly not before Node existed).
Also NodeJS may indeed handle the event loop well from the articles I see on the topic. It's just unfortunate that because of the DOM background that basing a runtime on JavaScript required an event loop rather than a choice between multi-threading or single threaded event loop.
I did years of multithreading (C, C#) before NodeJS (btw, NodeJS also has thread support).
The main problem with threads is switching between them. Each switch costs a lot of memory shifting and CPU cycles. Event loop is computationally cheap.
Hence, NodeJS is high performant in I/O heavy tasks (e.g. networking).
Ah okay thanks for explaining.
Now I am curious why other languages don't do single threaded. or maybe it depends on the task and entire language setup. Or is it the difficulty of doing an event loop well that meant it took a long time for node to eventually be the first?
Good questions. I wish I knew the answers.
Thanks for being open minded. You are a rare breed. 👍
I've updated my post to be more balanced and to point to your initial comment
Looks great! 👍👍👍