Nodejs vs Play for Front-End Apps

by Subbu Allamaraju on March 26, 2011 · 156 comments

Mar 29, 2011: The source used for these tests is now available at https://github.com/s3u/ebay-srp-nodejs and https://github.com/s3u/ebay-srp-play.

Mar 27, 2011: I updated the charts based on new runs and some feedback. If you have any tips for improving numbers for either Nodejs or Play, please leave a comment, and I will rerun the tests.

We often see “hello world” style apps used for benchmarking servers. A “hello world” app can produce low-latency responses under several thousands of concurrent connections, but such tests do not help make choices for building real world apps. Here is a test I did at eBay recently comparing a front-end app built using two different stacks:

  1. nodejs (version 0.4.3) as the HTTP server, using Express (with NODE_ENV=production) as the web framework with EJS templates and cluster for launching node instances (cluster launches 8 instances of nodejs for the machine I used for testing)

  2. Play framework (version 1.1.1) as the web framework in production mode on Java 1.6.0_20.

The intent behind my choice of the Play framework is to pick up a stack that uses rails-style controller and view templates for front-end apps, but runs on the JVM. The Java-land is littered with a large number of complex legacy frameworks that don’t even get HTTP right, but I found Play easy to work with. I spent nearly equal amounts of time (under two hours) to build the same app on nodejs and Play.

The test app is purpose built. It includes a single search results page that renders search results fetched from a backend source. The flow is simple – the user submits some text, the front-end fires off a request to the backend, the backend responds with JSON, the front end parses it, and renders the results using a set of HTML templates. The idea of this app is to represent front-end apps that produce markup with/without backend IO.

In my test setup, the average result from backend is about 150k – it is JSON formatted and not compressed. The results page consists of 8 templates – each for different parts of the page like header, footer, sidebar etc. The sizes of the template files range from 250 bytes to under 2k. In order to ensure that backend latency does not influence testing, search requests are proxied through Apache Traffic Server acting as a forward proxy. The cache is tuned to always generate a hit. Such a high cache hit is not realistic, but it helped me isolate the cost of having to go through uncontrolled public Internet to get search results for my testing.

Note that the test environment is not the most ideal – the test client, the server, and the cache were all running on the same box. The box is a quad-core Xeon with 12GB of RAM running Fedora 14 (2.6.35.6-45.fc14.x86_64 kernel).

I ran the tests using ab.

ab -k -c 300 -n 200000 {URI}

The tests include the following configurations

  • Render – No IO: Render the page without any IO – this configuration generates HTML from the templates with empty results.
  • IO + Render: Render the page with results.
  • IO – No Render: Fetch results but don’t render – this is an unrealistic case, but it helps highlight the cost of IO vs cost of template processing.

The charts below show requests per second and mean response time.

From these, you can see that Nodejs beats Play on performance as well as throughput. However, in the pure IO case, I would not discount non-blocking IO on the JVM. I plan to post more results dealing with IO + computation scenarios.

The charts below show the percentage of requests completed within a certain amount of time in msec. The shorter the bars the better. Also less variance as you read from left to right on each chart is better – I would ignore the last set of bars on the right (time to complete 100% of the requests) as they may contain outliers.

When the workload involves generating HTML from templates off the file system without performing any other IO, nodejs does twice better than JVM based Play. As we introduce IO, performance across the board suffers, but more so with blocking IO on Play. But Play is able to catchup with non-blocking IO (via continuations).

I’m unable to make the source code for the test apps available publicly at this time. But I plan to create and post some new tests on github soon.

{ 148 comments… read them below or add one }

Portal scala.net.pl (@ScalaPL) March 9, 2012 at 3:44 pm

“@iamwarry: I’m really curious to see what the results would be with #Play20 : http://t.co/rjsA5FC1 #node vs #playframework”

Reply

Paulo November 20, 2012 at 7:26 am

yeah, me too!
Play has seen a lot of development in the past couple years, and so did node.js.
I’m eager to see a comparison.

Reply

opensas March 10, 2012 at 10:52 am

Yes, me too

Play2 already has a RC4 version, so I guess a public release will be ready pretty soon. They rewrote the core in scala, with akka, and the templates are now statically compiled, so I think it should perform better

Reply

AK2= A.KarriemA.K (@ak2webd3) March 14, 2012 at 6:39 pm

@Klout C #Nodejs vs #Play 4 #FrontEndApps C http://t.co/AWk0x7wr
5/11 source #NodeJS http://t.co/v1HHZT3c & #Play111 http://t.co/I10lGk5t

Reply

Andrew's Saved Links (@andrewlinks) April 17, 2012 at 10:20 am

Nodejs vs Play for Front-End Apps: http://t.co/ksoJMMJo

Reply

Lincoln Stoll April 29, 2012 at 6:17 pm

It looks like the Play execution pool was left at the default setting [1], meaning play requests would have been processed over 5 threads. This is already a worker concurrency deficit over the 8 allocated for the node app on top of that.

Being that the workload is more IO than CPU oriented, and that threads are in ways a higher level abstraction over event loops [2] it would be interesting to see the benchmarks on an even playing field (8 worker threads). I also suspect at this level CPU usage at max throughput on the play app would still be quite low, you could probably increase this number quite a bit (16? 32?) and allow the thread scheduler to handle the non blocking IO. This should easily give you a much higher level of throughput, while still keeping a nice, non-callback oriented programming model.

[1] https://github.com/s3u/ebay-srp-play/blob/master/conf/application.conf#L172
[2] It’s a rant, but it covers the area pretty well: http://teddziuba.com/2011/10/straight-talk-on-event-loops.html

Reply

Subbu Allamaraju April 29, 2012 at 6:59 pm

Regarding [2], it is on the walls of “Node.js Hall of Trolling” :)

Reply

Lincoln Stoll April 29, 2012 at 7:02 pm

Oh yes, it definitely is. I unfortunately couldn’t find a less trolly explanation of my point at short notice though :)

Not meaning to use it as a troll for node, just a point that simply increasing the thread pool in play might simply ‘compensate’ for the IO blocking, without having to mess around too much with your code.

Reply

Subbu Allamaraju April 29, 2012 at 7:06 pm

I agree. In either paradigm, the amount of CPU is fixed whether it is sliced with threads or processes.

Reply

James Ward April 30, 2012 at 5:37 am

I created a Play 2 version of this app:
https://github.com/jamesward/ebay-srp-play/tree/play2

The WS parts don’t work yet. But the basic index page is testable. On my laptop the compiled Scala templates gets about the same requests/second as the Groovy templates in Play 1.

I also tested the Play 1 app with just a very minimal server-side template and it went from about 2800 requests/second (the original index page) to 9155.21 requests/second. So there is definitely a lot of overhead as the complexity of the template increases.

Interesting stuff.

-James

Reply

Subbu Allamaraju April 30, 2012 at 8:23 am

Great. How about a pull req?

Reply

Niklas Saers (@niklassaers) July 28, 2012 at 3:13 am

Is this still the best Node vs Play comparison, or is there a Play 2.0 version of this around? http://t.co/ECMazfWl

Reply

Truong Hoang Dung (@revskill) August 7, 2012 at 4:56 am

Nodejs vs Play for Front-End Apps http://t.co/T4DEa8KB

Reply

Prateek Temkar (@PrateekTemkar) September 28, 2012 at 11:20 am

#Nodejs vs #Play framework comparison. http://t.co/KphU0uTN

Reply

NodeJS Community (@NodeJsCommunity) September 28, 2012 at 11:46 am

#Nodejs vs #Play framework comparison. http://t.co/MShMNinB http://t.co/DWGMKYlM

Reply

@satrioarifw February 16, 2013 at 6:58 am

Nodejs vs Play for Front-End Apps http://t.co/n5ivP0XT

Reply

Leave a Comment

Previous post:

Next post: