Tuesday, January 28, 2014

Node vs. Java - Web Service Performance

Summary

I recently did some comparative testing of web service implementations for a simple in-memory cache. I built functionally equivalent interfaces in Java (REST + SOAP) and Node.js (REST only) for the cache.  As expected, the Node implementation outperformed the Java variants significantly (>100% faster response times).

Cache Implementation

Figure 1 depicts the high-level structure of this cache application.  The cache supports inserts, fetches, and deletes of key/value pairs.
Figure 1
Figure 2 depicts a bit more detail on the physical layout of the application.

In the cases of the REST variants for Java and Node, cache operations are implemented as HTTP verbs (Insert = PUT, Fetch = GET, Remove = DELETE).  Stale entries are cleared from the cache using timeouts with Node and scheduled threads in Java.  Additionally, cache redundancy (loose coherence) is supported simply by utilizing REST calls between the server peers (PUT's and DELETE's).

For the Java SOAP variant, cache ops are implemented with the typical HTTP POST of SOAP envelopes.

Figure 2
Application Organization

Figure 3 below depicts the organization of the Java REST variant of the cache.  Apache Tomcat + Jersey (servlet) are leveraged.

Figure 3


Figure 4 below depicts the organization of the Java SOAP variant of the cache app.  Tomcat + Apache Axis2(servlet) are leveraged.


Figure 4


Figure 5 below depicts the Node.js implementation.  A single worker process is utilized.

Figure 5
Testing
Figure 6 depicts the test environment I used.





Java + Node REST Cache Insert Test
ab -A username:password -u restput.txt -n 1000 -c 1 https://server/ctispan/rest/key/111 > results.txt

restput.txt
value=test111

Java SOAP Cache Fetch Test (I used TCP/IP Monitor in Eclipse to figure out the SOAP formats for ab)
ab -A client:password -T "application/soap+xml; charset=UTF-8" -p soapget.xml -n 1000 -c 1 https://server/ctispan/services/CacheProxyWS.CacheProxyWSHttpSoap11Endpoint/ > results.txt

soapget.xml
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body><ns1:getValue xmlns:ns1="http://server.ctispan.jwisoft.com"><ns1:key>111</ns1:key></ns1:getValue></soapenv:Body></soapenv:Envelope>

Java SOAP Cache Insert Test
ab -A client:password -T "application/soap+xml; charset=UTF-8" -p soapput.xml -n 1000 -c 1 https://server/ctispan/services/CacheProxyWS.CacheProxyWSHttpSoap11Endpoint/ > results.txt

soapput.xml
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body><ns1:putValue xmlns:ns1="http://server.ctispan.jwisoft.com"><ns1:key>111</ns1:key><ns1:value>text111</ns1:value></ns1:putValue></soapenv:Body></soapenv:Envelope>


Results
Below are some graphs of the numbers ab produced.  I wasn't really surprised by the Node vs. Java results.  The Java REST vs. SOAP numbers were a little surprising.  I expected a wide margin between Java REST and SOAP (in REST's favor) due to the overhead of SOAP.  All I can surmise is the Apache Axis2 API is significantly more efficient than the Jersey API.





9 comments:

  1. please use java Netty/Vert.x instead of tomcat + Jersey.

    ReplyDelete
  2. Did you use Tomcat with NIO connector along with Async Servlet ? If no then please try, result would have been very much different then. Adding more, we can also set JVM flags ,setting them can also help improving performance.

    ReplyDelete
  3. Thanks for sharing this. I am sure they are useful.

    ReplyDelete
  4. You are probably comparing asynchronous node to synchronous java. Please use asynchronous Servlets or better yet use the Play Framework or Vert.x as Norman has suggested. As is, this is an apples to oranges comparison.

    ReplyDelete
  5. I second comments / concerns about asynchronous Java / NIO. Could you provide test results using https://grizzly.java.net/ on Java side.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete
  7. Your benchmark is definitely wrong. Use plain async servlets or even netty/grizzly. Then you'll have different benchmarks.

    ReplyDelete
    Replies
    1. I have a better idea. Why don't you perform your own test and post the results?

      Delete
  8. Netty/Nio would be a good comparison to these

    ReplyDelete