Live data from Hacker News

What makes Node.js faster than Java? In a nutshell, it's all about concurrency

strongloop.com

41–50 of 59 posts

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#41
post #21

I have gotten to the point where I just can't take seriously anyone who equates "the async style" to "Node's event based system" as if Go, Erlang, Scala, Clojure, etc. don't exist. No, you do not have to choose between speed and sacrifice a sane coding style, and anyone still pushing that Node propaganda is just not worth listening to. Node is consistently beaten by multiple Go and Java frameworks across all benchmar…

What about generators and stuff like Koa[1]? Do you dismiss them too? You don't have to use events all the time, and it's trivial to wrap most Node IO as promises, thunks or whatever it is that you like, and then use generators as syntax sugar to work with them. [1]: http://koajs.com

Still incredible hacks compared to a language that just does it right, you get composition problems with having so many techniques floating around that require adapters to work with each other, and you're still writing a ton of code that is simply paperwork, that the compiler could be doing instead. And it's nasty, error-prone paperwork too.

Remember, Node did not originate a single one of those techniques, despite what it sometimes sounds like. They're rediscovering them from the other communities that tried them, and subsequently discovered that the techniques did not solve their concurrency problems. Watching the Node community has been like watching the greater concurrency community's last 40 years compressed into 4 years; we are right on the verge of the inevitable recognition that these techniques won't save them either (I'm seeing the first traces of this in various blog posts), followed by an eventually dimming of Node's vitality as it slowly becomes clear that Javascript just can't do what Node is asking it to do, at scale. (Can not emphasize the "at scale" enough. Anything works on small cases. Node is good enough to work at medium cases, though the effort starts getting greater distressingly fast, which is only noticed by those who have worked in a saner environment. But it's just not going to work at scale any more than any of the other half-a-dozen virtually identical languages with virtually identical capabilities and virtually identical programmers.)

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#42
post #21

I have gotten to the point where I just can't take seriously anyone who equates "the async style" to "Node's event based system" as if Go, Erlang, Scala, Clojure, etc. don't exist. No, you do not have to choose between speed and sacrifice a sane coding style, and anyone still pushing that Node propaganda is just not worth listening to. Node is consistently beaten by multiple Go and Java frameworks across all benchmar…

Why is it a dangerous coding style? The new Node will have support for yield / generators that result in beautiful async code.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#43
post #19
post #5

At first, I was ready to dismiss this article completely. However, this paragraph: "While Java or Node or something else may win a benchmark, no server has the non-blocking ecosystem of Node.js today. Over 50k modules all written in the async style, ready to use. Countless code examples strewn about the web. Lessons and tutorials all using the async style. Debuggers, monitors, loggers, cluster managers, test framewor…

> no server has the non-blocking ecosystem of Node.js today. Over 50k modules all written in the async style, ready to use. I read it as -- "Node.js doesn't properly support isolated units of concurrency and thus due to being forced to write callbacks inside callbacks that call errbacks for everything, we now have over 50k modules full of callback chains and we call this a GoodThing(tm)".

I don't think that's entirely fair. The standard callback model can easily be converted to a promise-based one with Q or a CSP channel-based one with ClojureScript's core.async or any number of other models.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#44
Node is certainly not faster in many cases AND in many cases nonblocking IO is NOT what you want. Sometimes sequential makes way more sense.

For example, I wrote a node script that would run a bunch of compilations of files for custom less and javascript minifacation and other stuff on a large codebase. Node opened so many file connections it would crush the machine and not finish.

A simple bash script ran in about a second.

My point is you should definitely NOT use Node because you think it's faster than Java in every case. In fact, evented everything is a pretty terrible trade off in terms of code quality for performance.

There are so many better/easier/cheaper ways to get a high performance, reliable system without using Node.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#46
post #19
post #5

At first, I was ready to dismiss this article completely. However, this paragraph: "While Java or Node or something else may win a benchmark, no server has the non-blocking ecosystem of Node.js today. Over 50k modules all written in the async style, ready to use. Countless code examples strewn about the web. Lessons and tutorials all using the async style. Debuggers, monitors, loggers, cluster managers, test framewor…

> no server has the non-blocking ecosystem of Node.js today. Over 50k modules all written in the async style, ready to use. I read it as -- "Node.js doesn't properly support isolated units of concurrency and thus due to being forced to write callbacks inside callbacks that call errbacks for everything, we now have over 50k modules full of callback chains and we call this a GoodThing(tm)".

While I'd tend to agree, this may be a case of "worse is better."

In the java ecosystem, most of it assumes blocking IO. If you're trying to get out of this mindset, the ecosystem can get in your way -- or at the very least, it's not making your life easier.

For many things, this is fine. If I'm not twitter, I'm trading increased scalability for readability almost every time.

For projects that just need occasional async, I would prefer the grails 2.3 model -- http://grails.org/doc/2.3.0.M1/guide/async.html -- which will get you 95% of the way there in a more readable way. ___

However, I am a bit more charitable toward node. I think this may be a case where there is enough momentum that, as people start hitting the harder problems, engineering solutions will sprout up, and the platform will mature with better patterns turning up (including generators and promises.)

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#47
post #21

I have gotten to the point where I just can't take seriously anyone who equates "the async style" to "Node's event based system" as if Go, Erlang, Scala, Clojure, etc. don't exist. No, you do not have to choose between speed and sacrifice a sane coding style, and anyone still pushing that Node propaganda is just not worth listening to. Node is consistently beaten by multiple Go and Java frameworks across all benchmar…

Why is it a dangerous coding style? The new Node will have support for yield / generators that result in beautiful async code.

Of course, beauty is in the eye of the beholder, but I would say yield statements are not beautiful, they're just less ugly. Having lots of yield statements sprinkled throughout my code is (again, in my eyes) ugly. Less ugly than callback pyramids, but still ugly.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#48
One discussion that tends to not be had in these types of benchmarks is about memory, resource utilization, and the fact that blocking is a feature.

In a typical multi threaded web application scenario, there's usually two main resources floating around: http thread pools, and database connection pools.

Both are typically designed to not scale up too quickly (e.g. wait a bit before adding a new resource) and block when they hit a configured maximum. This is because it is pretty easy for a single web server these days to become a denial-of-service attack on a database, and it's also pretty easy for a single client (especially as the typical home's Internet bandwidth increases) to become a denial-of-service attack on a web server. Sensible defaults should therefore take into account that a web server should be a good actor in an ecosystem, not that a web server should be a requests-per-second speed demon. When I read benchmarks, I tend to believe that they are essentially testing these defaults, because there is rarely discussion of them. A conservatively tuned database connection pool will block earlier in the load test, but I will respect the conservative defaults of the framework in question.

Memory is also crucially important in the sync-vs-async discussion. Once you decouple request state management from a constrained-sized thread pool, you have to predict how much memory each state will consume. Unless you are doing very little work on each request (and the work will go up as you add features), you will consume your web server's memory with request state far before you exhaust its other resources. In a threaded model, the thread overhead itself takes a lot of memory, so request overhead per thread in a threaded model is higher than an async model. But when you're talking about a web application with increasing numbers of features, this becomes less and less the majority of the request.

Here's a sketch of an example. In the typical thread-pool based model, X requests can happen simultaneously based on the configured maximum of handler threads--if more requests come in than can happen at the same time, they go into a queue. This is nice because unless the web application is very simple, it's far easier to predict the memory overhead of http requests in a queue than active simultaneous requests in the application layer, especially because most web servers put maximums on the size of individual http headers. In other words, the memory cost of each http request in the queue is constant, while the memory-per-request-state in the application layer will grow with the number of features that layer on the application.

Of course none of the above has much to do with asynchronicity vs thread-bounded-ness. You can have a web server with a request queue and then a set of asynchronous handlers that feed off the queue. I do have a weak argument for threads in this scenario. In the constant tug-of-war between server resources and request throughput, monitoring becomes very important. In a thread-based-model, it is easy to use operating-system tools to introspect the threads because the operating system knows what they are. In the asynchronous model the process is a heap of undifferentiated ram. In that scenario you need good tooling to predict how well tuned your request state is relative to resources. In the JVM it's pretty easy to do a heap dump and see how much memory each request is taking, I'm not sure if there's an equally convenient scenario in the Javascript runtime(s) Node.js can utilize, but I'm sure there's a way. What I do know, however, is that complexity increases as you add actors and/or callbacks, because request state is now broken into a chain of independent memory consuming entities, as opposed to a single predictable thread stack and references.

In the midst of all the above I tend to go for flexibility, because the needs are situational. Async when you need it, sync when you need it. With sync being the more predictable model for the above reasons. Async is great for socket servers that are fronting a fixed-sized memory store, like memcached, while sync is more predictable (using today's tools) for a user facing web application with non-fixed per-request costs.

Seriously, though, YMMV. The discerning reader will see that I'm not making a fundamental argument for threads or async, because on one level there is no difference between them. Threads are not coupled to CPU cores, so they themselves are floating request state stack waiting to be scheduled by the OS onto a core. Async request state is a further level of application level decoupling where a pool of requests are waiting to be scheduled onto a thread, which in turn will be scheduled onto a CPU. A second difference has nothing to do with sync vs async but with coupling -- a synchronous model implies utilizing a stack that executes one-at-a-time, while an asynchronous model implies message passing (hence the ability for selective parallelism). Both models have pros and cons when it comes to predictability and resource utilization. The separation between the two will probably end up being a historical artifact.

I'm just sketching some things that I think about when reading all these sync vs async benchmarks, because they're kind of like saying that American cars are slower than German cars because of average speeds on the Autobahn vs the 405 in Los Angeles, without a discussion of the posted speed limits, traffic patterns, etc.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#49
post #37

Java blocking I/O is faster than non-blocking, at least on Linux. This is kernel level, not language level. http://www.slideshare.net/e456/tyma-paulmultithreaded1

You have to be very careful what you mean by "faster" in this case. For the use case documented in those tests I assume he was measuring sustained throughput (it isn't documented well what he means by 25% slower). He was also testing a server that had lots of connections and not many messages per connection. In that case modern Linux can scale threads very well.

I've done tests in other cases where NIO had nearly the sustained throughput of the blocking libraries, but had much less jitter. That is the latency through the server was much more consistent with NIO libraries than with the blocking ones. This was in a protocol with few connections but lots of messages per connection.

So blanket statements about the blocking IO vs the NIO libraries being faster require more nuance than that.

Re: What makes Node.js faster than Java? In a nutshell, it's all about concurrency

#50
post #40

Earlier quoted context omitted.

PlayFramework (which I can't recommend enough) makes async and continuations super easy in Java. http://www.playframework.com/documentation/1.2.7/asynchronou... Play also dramatically improves Java's general... cruftiness.

Your link points to the (very old) 1.x branch docs. http://www.playframework.com/documentation/2.2.x/JavaAsync

yeah I was about to say the same since 1.x and 2.x are drastically different
Post reply on HN