By John Jenson
If you spend much time searching the web to figure out whether Java or Node is faster, you will find plenty of people claiming that Node is faster, and a slew of others claiming the exact opposite. Simply put, Java’s performance is amazing. Java can even outperform C++ because of the genius of its JIT compiler. If that is true, how can people make claims that Node is faster? Well the reality is that Node isn’t faster than Java at raw computational tasks, but when it comes to IO related tasks there is no contest. If we look at the types of tasks that we might want to perform for a typical web application, the claim that Node is faster is spot on.
In order to understand how Node beats Java, you have to consider 3 factors: IO, Concurrency, and Computation. All 3 factors contribute the overall speed and throughput of an application.
Java’s IO is blocking. Any operations that require it to write to disk or send data on the network, blocks it from doing anything else. The thread processing an IO operation gets stuck in a wait state and cannot do anything else until the operation is complete. (While it is possible to do non-blocking IO with Java, there is very little support for it, and it remains widely ignored)
Java and Node achieve concurrency in the web frameworks in two very different ways.
Java dedicates a thread per each incoming request that is processed. As the number of concurrent requests grows, the number of threads also has to grow. If you plan on processing up to 100 simultaneous requests, then you will need to a pool of 100 threads available for processing.
Node, on the other hand, uses a single thread to process all incoming requests. Because Node is non-blocking, it has plenty of time to do all the computations and transformations for all the requests while it is waiting for any IO operations.
Web Applications are IO Heavy
Web Applications do a lot of IO. First, a request is received from the browser; that’s IO. Second, the application typically fetches the requested data from a database; that’s IO. Once it has all the response data computed, it then sends it back to the browser; that’s IO. All the while, the application is probably maintaining an application log, and that’s IO too. Web applications, in fact, spend most of their time doing IO, not computation.
If servicing each request were a race between the two technologies, every time more IO is performed, Node would win a little bit more. What this amounts to is that Node is incredibly well suited for web applications.
Web Applications Require High Concurrency
How many web applications can you think of that are only accessed by one person at a time? Since Java must dedicate a thread for the life of each request, it demands a lot of threads to achieve concurrency. This doesn’t seem like a big deal, and in fact it isn’t if you only have a few users, but if your user load increases, time slicing between all those threads quickly becomes very costly and inefficient. Eventually as the number of threads gets too high, the operating system becomes so busy time slicing between all the threads that it doesn’t have any CPU time left to do any actual work.
The efficiency of Node becomes really apparent at scale. When Node is running at max load, although the CPU will be very busy, the operating system won’t even break a sweat. All of the CPU time will be spent doing exactly what you want, servicing requests.
In order to prove to myself that Node truly could outperform Java, I wrote a simulator that I could use to test the performance of the two technologies. I used the simulator to create various scenarios where I expected that Java would win and scenarios where I expected that Node would win. The code for this simulator can be found here:
The results are as follows, and show that Node out performs Java in scenarios that most closely match real world web applications. But, in purely computational scenarios, Java does indeed win.
A Note about the Java implementation
I chose to simulate blocking IO for the Java implementation. Some may argue that using blocking IO isn’t a fair comparison of Java’s performance, but here is why I think it is both accurate and fair. Java’s JDBC spec remains a blocking spec. That means that whenever anyone connects to a relational database using a standard JDBC driver, they have to block. Secondly, Apache Tomcat 8.5 finished implementing the first non-blocking servlet spec only seven months ago in June of 2016, so that means that the overwhelming majority of production Java applications still block when they do IO. So since Java is being used in a blocking way currently by most organizations, I feel it is the most representative of the Java to block in these simulations as well. I have written more on this topic in my post: Node: A Compelling Choice for Java Developers.
Scenario 1: Barebones Computational Speed
In our first scenario we decided to pick a purely computational workload to prove Java’s computational dominance. We do it with and without concurrency.
You can see that even with a purely computational task, as soon as concurrency is added to the mix, Node cuts into Java’s lead.
Scenario 2: IO Heavy Example
In the second scenario, we do no computational work. We only perform IO tasks. We do it with and without concurrency.
Once again, adding concurrency gives Node a chance to flex its muscles, but the difference is much more noticeable now.
Scenario 3: Balanced Workload
In the third scenario, we perform a more balanced workload of both some IO and some computational tasks. This is closest to what a typical request workload might look like. We do this with and without concurrency.
Scenario 4: Long Running Query
The last scenario illustrates how a long running query has a very negative impact in Java, but would barely be noticed by Node.
When it comes to real world scenarios seen in typical web applications, Node truly is faster and more scalable than Java. For web application development Node’s performance is hard to beat. Because web applications spend most of their time doing IO, and require high concurrency, Node is the clear winner.