Using Node.js PayPal Doubles RPS, Lowers Latency, with Fewer Developers, but Where Do the Improvements Really Come From?
PayPal gives yet another glowing report of an app rewritten in node.js experiencing substantial performance improvements. PayPal rewrote their account overview page, one of the most trafficked apps on the website, which was previously written in King Java.
- Built almost twice as fast with fewer people
- Written in 33% fewer lines of code
- Constructed with 40% fewer files
- Double the requests per second vs. the Java application.
- 35% decrease in the average response time for the same page.
A common pro Java response is an argument like clearly these people don't know how to program Java. Or rewriting an application usually makes it faster. Or the benchmark is faulty. And so on. Consider it noted. These are all potential factors.
Baron Schwartz from VividCortex has a different take. One based on math. Using the Universal Scalability Law (yes, there is such a thing), which models why a system’s performance degrades under higher concurrency, Baron performed an Analysis of PayPal’s Node-vs-Java benchmarks. The power of the USL is it can pinpoint which factors are to blame for non-linear scaling. The findings:
Notice that Java’s sigma (serialization) parameter is lower and its kappa (crosstalk) parameter is higher than Node.js, and the reverse is true for Node.js. This means that Java is bottlenecked less on serialization, and Node.js is bottlenecked less on coherency delays. This is exactly what one should expect from their architectures (multi-threaded versus single-threaded with event loop) and their blog post (“using a single core for the node.js application compared to five cores in Java”).
Curiously, Baron also found that both Java and Node should be performing much better than they do. We should be seeing many hundreds of pages a second instead of the 1.8 pages/sec for a single user in Java, and 3.3 in Node.js. Why? That's unclear and is a good topic for a much deeper dive into the stack.
Why might Node be faster than Java? Baron surmises:
My guess is that Node is encouraging good programmer practices in terms of scalability, and Java less so. In other words, programmers probably have to work less hard to avoid bad scalability bottlenecks in Node than in Java
Lots more details in Baron's excellent post.
There are also some good comments on the post, reinforcing the idea that doing the more parallel thing may be just easier in Node.
From Michael Holroyd:
If Paypal’s application is hitting a high-latency API this makes a lot of sense. Node strongly pushes the developer toward a non-blocking asynchronous style of programming, that is difficult to achieve in Java without understanding multi-threaded programming and increasing complexity. I’ve find the same thing in our experience at Arqball while switching to node — many applications have become *much* faster when rewritten for node thanks simply to getting work done while waiting on “slow” events (db, disk, cpu). Of course this concurrency is also possible with other technologies (Ruby in our case), but in practice we would only multi-thread applications if performance became a bottleneck for us.
Yes, that’s been our experience; we do web development in PHP, Perl, Python, and Node.js, and because our typical clients are oriented toward highly scaled systems, Node.js matches up well with that model “by default”, so it’s become very popular amongst our devs
Your argument about Node encouraging good scalability practices versus Java I think is spot on – this was exactly my point, though I took it further to say that Java hinders good scalability practices
So what have we learned? Node.js continues its march into the core. The lure of full-stack engineers using a naturally performant language running on a platform with a huge software base is hard to ignore. Using the Universal Scalability Law is an interesting way to look at system performance. Java and Node are slower than they should be. And it would be curious to see if a Java app rewritten in Akka would perform as well as when written in Node?