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:
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)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 }
Next Comments →
RT @sallamar: On the blog – "Nodejs vs Play for Front-End Apps" http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
RT @sallamar: On the blog – "Nodejs vs Play for Front-End Apps" http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
Nice article. Thanks for the insight.
Could you elaborate more on the “legacy frameworks that don’t even get HTTP right” part? How do they get HTTP wrong?
thanks
Nodejs vs Play for Front-End Apps http://bit.ly/g8soXM
Nodejs vs Play for Front-End Apps by @sallamar http://bit.ly/fODdnP
RT @lsinger: Nodejs vs Play for Front-End Apps by @sallamar http://bit.ly/fODdnP
Encore une preuve que play déchire tout! “@rmat0n: Nodejs vs Play for Front-End Apps http://t.co/cCqyEOr #nodejs #play”
RT @FabienAMICO: #Nodejs vs #Playframework for Front-End Apps – http://goo.gl/oPeMS
RT @naholyr: Nodejs vs Play for Front-End Apps http://goo.gl/G2wwM
how many cluster workers? NODE_ENV=production? seems like lots of information is missing… I can get better numbers than this on my machine, but if you leave NODE_ENV to development with Express view rendering will be much much slower
Cluster starts 8 instances. Good tip about “NODE_ENV=production” – will look into that.
I updated the charts with NODE_ENV=production. You’re right about production mode. V8 seems to take a lot of strain (particularly CPU) when production mode is not enabled.
Was Play in dev or production mode, application.mode=dev or prod?
NODE_ENV is not production, express will re-compile the template on every request, so this will slow it down greatly
@TJ: That’s what I though by looking at the CPU activity without NODE_ENV=production.
@Ile: Play is run with “application.mode=prod”
Yes, I think I missed that in the article. Nice work.
RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
empezó la pelea! #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
What version of Node are you using?
Node v0.4.3
"Node.js" performs twice better than JVM MVC Framework "Play" for Front-End Apps http://goo.gl/GqT4P – V8 will only improve from here.
Nodejs vs Play for Front-End Apps http://goo.gl/fb/hQeXx #hackernews #kalimba
Nodejs vs Play for Front-End Apps http://goo.gl/fb/oX7sT
Looking forward to seeing a benchmark with source. Showing results without source code is less useful.
Mike – the source is now github. See the links at the top of this post.
RT @tek_news: HNews: Nodejs vs Play for Front-End Apps http://bit.ly/eOgzzY #nodejs #benchmark
RT @indexzero: Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8
RT @sallamar: Updated http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps based on new test runs, and these numbers are better :)
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
I should note as well ejs is not highly optimized due to the use of with. I don’t know of any faster for node, but it would be easy to write something like mustache that is very very fast, the restricted syntax would allow removal of the slow with(){}
#Nodejs vs Play for Front-End Apps http://bit.ly/f4LcY0 #geek #performance #server
RT @indexzero: Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8
RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
RT @nmartignole: Nodejs est plus performant RT @sylvain_mathieu: #nodejs vs #playframework for Front-End Apps http://bit.ly/eB4EvP
RT @sallamar: On the blog – "Nodejs vs Play for Front-End Apps" http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
RT @maboa: Some node.js benchmarking: http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps (via @trygve_lie) Interesting.
Node.js vs Play for front end apps http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
RT @jedisct1: NodeJS vs Play framework benchmark: http://bit.ly/fODdnP
RT @indexzero: Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8
RT @maboa: Some node.js benchmarking: http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps (via @trygve_lie) Interesting.
Great works!
Play! outperformes Node.JS without render. Play! uses Groovy for the template engine. The bottleneck may be Groovy.
Are you aware of alternatives? I just found about http://code.google.com/p/cambridge/ – but I’m vary of template languages that expect well-formedness.
Thanks for this link! It may be an alternative to Groovy.
Could you run the tests without the Groovy based templating? It would be useful to see the performance when using JSON responses based on the internal Gson library used by Play!.
@Frank: Other than a few conditionals, most of the processing is done using Gson. There is no intermediate model object between the backend response (JSON) and templates other than Gson. The controller passes a Gson object to the view, and view templates iterate through that.
So there’s no Groovy stuff happening and explaining the slowness with rendering?
Any idea why the rendering phase is so slow compared to Node? If that was solved, Play! would be a clear winner when using NBIO.
Hi,
I’m the author of Cambridge Template Engine and I wanted to clarify something. Cambridge doesn’t require your template files to be well-formed. It doesn’t use any xml parser to parse the templates, it has its own parser and it works fine with any non-xml/non well-formed template file. Here is a performance comparison of built-in play templates with Cambridge templates: http://code.google.com/p/cambridge/wiki/UsingWithPlayFramework
Thanks for the clarification. I will take a look. In the meantime, I’ve made the source available on github. See the top of this post for links.
RT @jfarcand: Play vs NodeJS….. RT @indexzero Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8 (via @mwessendorf)
RT @indexzero: Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8
RT @perfengineering: Nodejs vs Play freamework for front-end apps: Throughput and Performance Benchmarking by @sallamar Nodejs wins. http://bit.ly/hIgvnb #perf
“Any idea why the rendering phase is so slow compared to Node? If that was solved, Play! would be a clear winner when using NBIO.”
@Frank: I’m going to find out this week, and try to post an independent test.
BTW, what does that “IO” consist of that is referenced in the article? I think it means “backend IO” but it’s not clear (at least to me) what it means?
@Ile: The same – it involves making an HTTP GET request to get JSON-formatted response through a proxy cache (Traffic Server) using play.libs.WS. I chose Traffic Server because, from my experience at Yahoo!, it handles large number of concurrent connections very well.
RT @jfarcand @indexzero @mwessendorf Node.js outperforms Play http://bit.ly/hlZKO8 >> Looking forward to follow-ups from the Play folks
RT @mariofusco: #Nodejs vs #Play for Front-End Apps http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps Interesting performance comparison
Nodejs vs Play for Front-End Apps http://ow.ly/4nuVr
Interesting numbers from the eBay guys on Node.js vs Play! – http://bit.ly/hlZKO8. server-side JS comes of age. via @smaldini
http://bit.ly/dPBbX6 記得 #playframework 幾個 core staff 之前在 maillist 捍衛內定使用 groovy template , 原因在於 view 效率不是那麼重要。現在果然被人抓來 benchmark…(雖然敗陣原因仍不明)
It’s hard to let go of egoism.
RT @jedisct1: NodeJS vs Play framework benchmark: http://bit.ly/fODdnP
RT @rgaidot: Nodejs vs Play for Front-End Apps http://t.co/FlWweNI #nodejs #playframework #java
Comparative: Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
RT @srishivananda: #Nodejs vs #Play for Front-End Apps http://bit.ly/eB4EvP
Next Comments →