About Node.js Performance

A rule of thumb is that Node is typically an order of magnitude faster than Python, Ruby, Perl, PHP; and an order of magnitude slower than Rust, C, and C++. Java and Go tend to fall somewhere in the middle between Node and C. Of course, performance always depends on what exactly you are doing, which is why this is just a rule of thumb.

Event Loop

Node popularized event-driven async programming by pairing an event-driven C library with an fast implementation (V8) of an event-driven programming language, and combined that with a package ecosystem that matches the event loop programming model. And the fact that Node is pretty fast compared to C is one of the remarkable things about it.

Node is essentially a nice JavaScript wrapper around libuv. One can certainly write a program in C using just libuv and have C-level performance.

There seems to be some confusion around this, but Node does not have a monopoly on the event-loop concept or have invented the event loop or asynchronous programming. (Windows 3.1 used this concept for cooperative multitasking.)

One could certainly write an event-loop driven program in other languages besides JavaScript. Rust, for example, has the projects mio and rotor for doing event-driven, asynchronous I/O. Remember though, if you want to write async, non-blocking code, all your code has to be async non-blocking because as soon as you introduce a blocking method call, it will hold up your event loop and cancel out all the benefits. Node.js has excelled at async I/O, because you pretty much have to write libraries in that style.

Java

Java will typically be a bit faster than Node for computation-heavy applications. However, consider “network glue” type application — this is Node.js’s wheelhouse, and the performance differences between Node and Java become very interesting here because they are due to other factors besides strictly the language itself. Below is a comparison of many characteristics of a basic RESTful web app that retrieves information from a database and returns JSON, written in both Node and Java on JBoss. Please excuse the older versions used.

Interestingly, the Java version uses 63 threads (for RMI, JMX, garbage collection, and who knows what else??) and always is using some CPU, while the Node process actually does not use any CPU when it is not doing any work.

The Java startup time is 100x longer. This is apparently due to Java classloading, because both the Java and Node.js virtual machines themselves start up very quickly. (The JVM itself starts up in 70ms and the Node VM starts up in 30ms.)

A Spring Boot app will startup quicker and use less memory than JBoss as it does not require an app server. With Spring Boot the difference tends to be about 10x instead of 100x, and memory usage is less. And of course, JBoss has many built-in features compared to Express, so of course one must take that into the consideration with the relative size of the two libraries.

On the other hand, if you look at the TechEm power benchmarks, some of the fastest web servers are written in Rust, C, Go, Java, Scala and C++. So ultimately performance depends on exactly what you are doing.