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.
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
RT @sallamar: Source for my nodejs vs Play tests are now on github – see http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
RT @sallamar: Source for my nodejs vs Play tests are now on github – see http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
RT @indexzero: Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8
@jneira "Node.js outperforms Java http://bit.ly/hlZKO8" Bad, bad info, Java != Play and Play is using Groovy for rendering != Java
@jmarranz @jneira Right. As the title of my post says, the comparison is just about Play vs Nodejs and not Java vs Nodejs.
RT @NicolasLabrot The source of the #Nodejs vs @playframework article is available http://bit.ly/eB4EvP. Thx @sallamar
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Node.js outperforms Java in full-stack tests at eBay: http://bit.ly/hlZKO8 /via @indexzero << where by "Java" you mean "Play"?
Any updates with the tests? I’m interested in finding out the reason for slowness in Play’s rendering.
It’s the Groovy Templates. Generate the output with one of the compiled template Play! modules, use NBIO (orange bars) and these numbers make a clear case for choosing Play! over of NodeJS.
Any recommendations? I did try Japid, but its compiler did not seem stable enough. It tripped on inline JS.
Do you have a use case of inline JavaScript that screws up the Japid compiler? I’m the author of Japid and very interested in knowing your case. Thanks!
Ok I saw the problem. $o5 near the end of the JavaScript block in the main.html was interpreted by the compiler as a template expression. The following will solve the ambiguity.
`verbatim
function $o5(p0,p1_4)….
`
That’s where I was getting the error. This was surprised me a bit. Any reason why this is required?
Subbu said earlier that: “@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, is Groovy the problem or not? If yes, I’m happy : )
@Frank – I’m working on alternative test that does not use Groovy. Pl stay tuned.
I have no idea if it matters, but Gson is a well-known to have sub-par performance as a JSON processor. So if it is indeed being used here, it can have significant negative effect on results (for example, in jvm-serializer benchmark gson is not included on all result charts because time taken is literally off the chart…). I don’t know if it’d be used by framework (harder to change) or explicitly; if latter, switching to faster alternative (jackson) should be easy.
For example, see:
* https://github.com/eishay/jvm-serializers/wiki
* http://www.cowtowncoder.com/blog/archives/2011/01/entry_437.html
* http://www.martinadamek.com/2011/02/04/json-parsers-performance-on-android-with-warmup-and-multiple-iterations/
RT @jedisct1: NodeJS vs Play framework benchmark: http://bit.ly/fODdnP
RT @jedisct1: NodeJS vs Play framework benchmark: http://bit.ly/fODdnP
hi,
this test is a good initiative.
but i have got some remarks:
-about the jvm:
can you publish the arguments of the command line used to launch the jvm?
which garbage collector is used? have you done some tweaks on the jvm?
is it an openJDK jvm, or the sun/oracle jvm (‘java -version’ can help you).
-about the charts:
your charts are confusing, because the Y axis does not start at 0.
for example, in the second chart (render no io), it seems that play! has got a mean time per request close to 100 msec, and nodejs close to 55 msec: there is a ratio of 2.
but your chart implies a ratio of 10, because the y axis start at 50 and not 0.
so, the y axis display 50 msec, with 5 for nodeJS and 50 for play!, in case of (50+5) for nodeJs, and (50+50) for play!
despite these two remarks, thank you for your this informative post.
best regards, charles.
@Charles
– JVM: The VM is OpenJDK
java version “1.6.0_20”
OpenJDK Runtime Environment (IcedTea6 1.9.7) (fedora-52.1.9.7.fc14-x86_64)
OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)
– VM settings – defaults set by Play. Note that neither CPU nor memory was too busy to warrant any tuning.
– Regarding the graphs, those were generated by Google docs. See http://tinyurl.com/3vgvfw2 for the raw data.
In production mode, Play will use the ‘server’ JVM that need a pretty long time to warm up since it uses a lot of dynamic analysis and just in time compilation during the first requests.
Do the results change if you run your tests a second time? (without stopping the servers).
Hi,
thanks Subbu to publish the google docs used to build graphics.
i’ve copied the spreedsheet, and updated the graphics with an ‘y’-axis origin starting from 0.
informations given by these graphics seems more impartial.
here is the link of the updated spreedsheet:
http://tinyurl.com/62p67yj
are you ok to publish the updated graphics ?
best regards,
Charles.
@Charles – thanks. I’ve just updated the charts myself so that they show up here. Sorry – I should have done it immediately after your first comment. I was swamped at work.
@Subbu,
thanks for the update!
best regards,
Charles.
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
RT: @ncoronges: Nodejs vs Play (java) for Front-End Apps http://t.co/Idbcr89” http://dlvr.it/NDH1H
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Nodejs vs Play for Front-End Apps http://t.co/Fm8b2lW
#nodejs vs play
http://www.subbu.org/blog/2011/03/nodejs-vs-play-for-front-end-apps
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Hi,
There has been some optimizing in Play 1.2 – some related to groovy-template-rendering, so you might try to rerun the test using Play 1.2
-Morten
Yes, please re-run the benchmark with the new Play! version.
The differences between 1.1 and 1.2 are marginal for this specific test. However, Java7 showed 10-20% improvement for all tests.
"…I did at eBay recently comparing a front-end app built using two different stacks"> Nodejs vs Play for Front-End Apps http://bit.ly/gaRZQQ
NodeJSとPlay(Java)の比較。 / Nodejs vs Play for Front-End Apps http://htn.to/7z7ydy
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Nodejs vs Play for Front-End Apps http://htn.to/Tz46d5
#playframework / Nodejs vs Play for Front-End Apps http://htn.to/Tz46d5
Node.js is 2x faster than @playframework – http://bit.ly/fODdnP
Nodejs vs Play for Front-End Apps : http://j.mp/hlZKO8 #nodejs #playframework
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Node.js is 2x faster than @playframework – http://bit.ly/fODdnP (via @mraible)
@michaelg I’m not talking about frameworks. I’m talking about framework *comparisons* http://goo.gl/GqT4P
@nodejs( #expressjs ) vs @playframework for Front-End Apps http://bit.ly/eB4EvP . Node.js is 2x faster than @playframework?
Nodejs vs Play for Front-End Apps http://bit.ly/eB4EvP
Nodejs vs Play for Front-End Apps: http://t.co/CwVMFOz
Play, NodeJS http://t.co/eDgBcXT
[node.js][javascript][play][java][benchmark][NIO] / Nodejs vs Play for Front-End Apps http://t.co/usatff0
"Nodejs vs Play for Front-End Apps" http://t.co/0rCS2mCJ #play_ja
Nodejs vs Play for Front-End Apps http://t.co/TEHX5cjX
Nice benchmark of #NodeJS applications : Nodejs vs Play for Front-End Apps – http://t.co/wH34uNxd
Node JS Versus Play BIO vs Play NBIO http://t.co/rxUsUMpN /cc @marianocortesi @guidomb
Nodejs vs Play for Front-End Apps http://t.co/iKPTL2mC
Node VS Play! http://t.co/jfFlmQJ1
PlayFrameworkとNode.JSの比較。Node.JSの方が2倍速い。http://t.co/55ZIO7Z7
RT @LightningX: PlayFrameworkとNode.JSの比較。Node.JSの方が2倍速い。http://t.co/55ZIO7Z7
RT @LightningX: PlayFrameworkとNode.JSの比較。Node.JSの方が2倍速い。http://t.co/55ZIO7Z7
RT @LightningX: PlayFrameworkとNode.JSの比較。Node.JSの方が2倍速い。http://t.co/55ZIO7Z7
[node.js][play]でしょうな / “Nodejs vs Play for Front-End Apps” http://t.co/RwPN004f
I’m really curious to see what the results would be with #Play20 : http://t.co/mfoE5vUq #node vs #playframework
RT @iamwarry: I’m really curious to see what the results would be with #Play20 : http://t.co/mfoE5vUq #node vs #playframework
“I found Play easy to work with. I spent nearly equal .. time (under 2hrs) to build the same app on nodejs and Play.” http://t.co/mEROOxxu
RT @iamwarry: I’m really curious to see what the results would be with #Play20 : http://t.co/mfoE5vUq #node vs #playframework
“@iamwarry: I’m really curious to see what the results would be with #Play20 : http://t.co/rjsA5FC1 #node vs #playframework”
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.
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
@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
Nodejs vs Play for Front-End Apps: http://t.co/ksoJMMJo
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
Regarding [2], it is on the walls of “Node.js Hall of Trolling”
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.
I agree. In either paradigm, the amount of CPU is fixed whether it is sliced with threads or processes.
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
Great. How about a pull req?
Is this still the best Node vs Play comparison, or is there a Play 2.0 version of this around? http://t.co/ECMazfWl
Nodejs vs Play for Front-End Apps http://t.co/T4DEa8KB
#Nodejs vs #Play framework comparison. http://t.co/KphU0uTN
#Nodejs vs #Play framework comparison. http://t.co/MShMNinB http://t.co/DWGMKYlM
Nodejs vs Play for Front-End Apps http://t.co/n5ivP0XT
Don’t you want to compare Nodejs with Vert.x?