Performance Comparison: Java vs Node

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? Check out our findings.

The Reality Check…

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.

Performance Factors

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.

1.  IO

While Java introduced nio several years ago, take a look at the servlet spec, Java’s de facto standard for writing backend server code. All throughout the spec, the API’s make the assumption that code can and will block at every level. While improvements to the spec over the last few years now allow non-blocking request handling, the fundamental paradigm for the servlet spec still fully embraces IO blocking. That means that operations that write to disk in a non-blocking way, or write to a database using JDBC, block the processing thread from doing anything else. While java is capable of working in a non-blocking way, it remains impractical for Java applications  that are based on servlet technology to successfully implement a non-blocking server. This is a major misfortune for the Java community.

JavaScript, on the other hand, fully embraces non-blocking IO through and through. Its API’s don’t provide an option for blocking, which forces non-blocking API specs at every level. That means that Node will never be blocked while IO operations are being performed, and it will always be free to process other work while waiting for IO. This allows Node to use the server’s processing and memory resources incredibly efficiently. It can process and issue thousands of IO operations at once with only a single thread.

2.  Concurrency

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.

3.  Computation

While Google’s V8 JavaScript engine compiles JavaScript into machine code to achieve impressive results, Java still has superior performance over Node. If you were to pit Java against Node in a contest of pure computation doing something such as computing the first 5000 prime numbers, Java would win quite easily every time.

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.

Performance Simulations

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:

https://github.com/johnrjenson/JavaVsNode

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.

java-vs-node-speed_scenario-3-1

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.

Summing It Up

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.

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? Check out our findings.

The Reality Check…

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.

Performance Factors

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.

1.  IO

While Java introduced nio several years ago, take a look at the servlet spec, Java’s de facto standard for writing backend server code. All throughout the spec, the API’s make the assumption that code can and will block at every level. While improvements to the spec over the last few years now allow non-blocking request handling, the fundamental paradigm for the servlet spec still fully embraces IO blocking. That means that operations that write to disk in a non-blocking way, or write to a database using JDBC, block the processing thread from doing anything else. While java is capable of working in a non-blocking way, it remains impractical for Java applications  that are based on servlet technology to successfully implement a non-blocking server. This is a major misfortune for the Java community.

JavaScript, on the other hand, fully embraces non-blocking IO through and through. Its API’s don’t provide an option for blocking, which forces non-blocking API specs at every level. That means that Node will never be blocked while IO operations are being performed, and it will always be free to process other work while waiting for IO. This allows Node to use the server’s processing and memory resources incredibly efficiently. It can process and issue thousands of IO operations at once with only a single thread.

2.  Concurrency

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.

3.  Computation

While Google’s V8 JavaScript engine compiles JavaScript into machine code to achieve impressive results, Java still has superior performance over Node. If you were to pit Java against Node in a contest of pure computation doing something such as computing the first 5000 prime numbers, Java would win quite easily every time.

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.

Performance Simulations

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:

https://github.com/johnrjenson/JavaVsNode

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.

java-vs-node-speed_scenario-3-1

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.

Summing It Up

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.

Interested in partnering with us?

Send a message and we will work with you to understand your needs.

Related Insights from Our Experts
2018-08-31T10:27:08+00:00