6 ms·
What makes Node.js faster than Java? In a nutshell, it's all about concurrency
- weddpros 13y agoI'm not sure node.js is faster than Java... My experience shows the contrary, but I switched to Node.js nonetheless. Node is fast... enough. And socket.io justifies using Node :-)
- eigenrick 13y agoYea. This headline has to be troll bait. NodeJS is not faster than Java, and it's also not Concurrent. It is single threaded. It makes efficient use of that single thread with an event-oriented model. That said, I tend to prefer building in NodeJS because it's fast enough for most (unanticipated) use cases.
- rgbrgb 13y agoThere's a difference between concurrency and parallelism. Concurrency is about a programming model for doing multiple independent tasks while parallelism refers to doing them at the same time. For example with node, you can handle requests while waiting for an asynchronous io task like reading a file. http://blog.golang.org/concurrency-is-not-parallelism http://blog.golang.org/concurrency-is-not-parallelism
- eigenrick 13y agoParallelism is doing different parts of the same task at the same time. Concurrency is doing multiple, different tasks simultaneously. Single threaded, event oriented systems can appear to be concurrent. They can never be parallel.
- nkozyra 13y agoYour operating system is concurrent even if it's single threaded. Concurrency is about doing things in the same time period not necessarily at the exact same time.
- nkozyra 13y agoThat said, saying (concurrent) Node is faster than (nonconcurrent) Language X is several distinct levels of stupid. If you introduce blocking into an application then to the user it slower, but in terms of computation it could still be faster by some magnitude. It's like having C block on a network call while having in-browser Javascript concurrently move past it and declaring Javascript faster.
- drdaeman 13y ago> Language X Actually, comparing runtime/platform (Node) to language is completely pointless. Language is, well, only a language, it can't be "faster" or "slower" unless we're talking about coding speed. We have to compare implementations. And even if we treat Java as a platform, contrary to Node it has ton of highly-varying implementations, so it's still pointless without careful clarifying what one compares. Or they may accidentally find out there's a Java variation with green threads somewhere that may break the whole "look, their ugly threads are slow and our event loops are fast" charm. The article is just a pure load of non-sense. Highly flammable, though.
- endeavour 13y agoIt's really not.
- nkozyra 13y agoThanks for your descriptive rebuttal.
- crimsonalucard 13y agoNode offers parallelism through load balanced processes. See cluster.
- memracom 13y agonode.js could be concurrent. You just run multiple node.js processes and leverage the tried and true concurrency of the UNIX process model, which Erlang architecture is based on.
- nobullet 13y agoI wouldn't be so sure with this statement: take a look at techempower's frameworks benchmarks and compare best configurations of NodeJS and PlayFramework (via genius Netty): http://www.techempower.com/benchmarks/#section=data-r8&hw=i7&test=query http://www.techempower.com/benchmarks/#section=data-r8&hw=i7... NodeJS is far behind with 55% vs PlayFramework 67% on 20-queries test.
- ebiester 13y agoAt 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 frameworks and more all expecting your code to be non-blocking async." is true. Java has had all of the same async capabilities for many, many years, but nobody uses them because the blocking paradigm is simply easier. That said, if true scalability is required, I'd suggest living with Akka and the cleaner actors paradigm. However, it's true that eventually you're going to run into the barrier that the vast majority of the java ecosystem is built on blocking io. (That said, with Java 8, I think we have a real opportunity to change that. I think a parallel "lean java" ecosystem is coming.)
- dj-wonk 13y agoRe: "Java has had all of the same async capabilities for many, many years, but nobody uses them" That's exaggeration. Lots of Java libraries use async and concurrency. Java 7 has NIO.2 which is easy to use. There is also Netty; many projects build upon that. I'm not here to say Java's ecosystem is richer or better; I'm just saying exaggeration is not useful. Re: "the vast majority of the java ecosystem" I don't mean to sound dismissive, but lots of languages have code you probably don't want to use based on your preferences or needs. So? Don't use the vast majority of libraries. :) You probably don't anyway. UPDATE: See also Akka and Clojure's concurrency for useful, popular approaches for the JVM.
- nostromo 13y agoPlayFramework (which I can't recommend enough) makes async and continuations super easy in Java. http://www.playframework.com/documentation/1.2.7/asynchronous http://www.playframework.com/documentation/1.2.7/asynchronou... Play also dramatically improves Java's general... cruftiness.
- saryant 13y agoYour link points to the (very old) 1.x branch docs. http://www.playframework.com/documentation/2.2.x/JavaAsync http://www.playframework.com/documentation/2.2.x/JavaAsync
- sheng 13y agoI'm always wondering why gevent never gets the same attention other concurrency frameworks do. From my point of view it looks like a very sweet library with useful tools and should work just fine in combination with gunicorn or uwsgi. I never had a chance to test it with some real work load though.
- camus2 13y agoProblem is the lack of third party libraries that does IO the way gevent works, if your lib does blocking IO, there is no point using gevent. NodeJS does async IO by default,so all nodejs libs do async IO. My point is , it's not so much about wether ruby or python can have the same capabilities as nodejs they can,it's about wether async libs have an ecosystem to support them or not.
- drdaeman 13y agoIf you lib uses standard library primitives (sockets, pipes, subprocesses, etc) then gevent.monkey makes it cooperate.
- jerf 13y ago"Problem is the lack of third party libraries that does IO the way gevent works, if your lib does blocking IO, there is no point using gevent." Here we probably see some of the problem. Gevent works in a way that most people don't expect, which is to hack the IO layer itself. You don't need a library to "support" gevent for it to still work within gevent. If the library's "synchronousness" is that it opens sockets and uses them, that Just Works in gevent; every time the library does a "blocking" operation in gevent, gevent replaces it with an entry in some sort of polling loop, and moves to the next eventlet that can do work. I used it to write a highly concurrent program that made a ton of simultaneous XML-RPC calls, and I used gevent + the default "blocking" XML-RPC library from Python's core library. It makes the ecosystem support async, at least for network, timers (sleep), and a few other things. Gevent has other issues; I don't think it can do the same for disk IO. But especially if you've got a network heavy program, you can just drop gevent in and get perfectly cromulent async. I think a lot of people don't quite understand this. The Node community's persistent and vocal false belief that "async == visibly event-based structure code" probably isn't helping. But it is also true that gevent is a legitimately weird hack on a language. Cool, but very unusual.
- camus2 13y agoIt's an "informercial" from a company which core business is providing nodejs commercial tools and consulting, what did you expect them to say about NodeJS ?
- jerf 13y agoI 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 benchmarks [1], consistently beaten by Scalatra, somewhat inconsistently beaten by the Haskell wai implementation (missing some benchmarks, I suspect wai would continue winning though if they were implemented; also I think those benchmarks are on an older Haskell IO manager). Not only are you choosing a dangerous coding style, you're not even winning the performance you think you are. Node is not faster. And certainly every library for Go, Haskell and Erlang, and probably everything for Scala and Clojure (not 100% sure of their runtime models) is already "async ready", and Java itself probably isn't exactly running short of libraries at this point. [1]: http://www.techempower.com/benchmarks/#section=data-r8&hw=i7&test=update http://www.techempower.com/benchmarks/#section=data-r8&hw=i7...
- skybrian 13y agoI agree, they should at least compare to Go. However, it is fair to say that when using Java, you have to choose carefully since many API's block on I/O, including those that Java programmers use by default and are most likely to be familiar with.
- saryant 13y agoThe biggest impediment to async programming in Java-land is the lack of an async JDBC driver.
- larsmak 13y agoIt's really not that hard to make thing run async / paralell in java: You just create a ExecutorService and submit your runnables / callables. The java.util.concurrent-package makes this easy, and google guava has some useful extensions as well (e.g. ListenableFuture). This approach does of course spawn new threads, but threads are lightweight and using a ExecutorService allows for pooling of the threads (ThreadPoolExecutor). I do this all the time, when I find parts of the code that's worth optimizing - e.g. fetching multiple objects from a distant db-server (like aws).
- tedsuo 13y agoSystems such as Go's goroutines, or clojure's core.async, or objective-c's GCD all solve the same concurrency problem while still allowing you to saturate all of your cores from a single process. This allows you to get around some nasty architectural problems you can hit with node, where you must either find a way to manually schedule all of your computation into tiny chunks to avoid latency issues, or face potentially severe costs serializing your data to communicate it between processes. No trolling here, it's really a thing that happens! People do solve these problems in node, it's just that the "ease" suddenly turns against you, as you must now solve tricky systems problems - such as manually scheduling all of your computation properly - or face potentially unacceptable performance degradation. In these cases the limitations of the platform become your overriding architectural driver - better drivers like logical separation start to take a back seat. It's not pretty - and not necessary in other environments. Given that you won't encounter these types of problems until later - once you've already built up a large codebase and switching platforms is difficult - I think it's better to start in an environment where you know you have these tools available to you when you need them. Even though I really enjoy programming in node (and I've done a lot of it!), I'm wary of starting anything new there unless I have a good reason. There are a lot of great modules written in node, I just try to keep those components isolated and not let them grow too large.
- rdtsc 13y ago> At high levels of concurrency (thousands of connections) your server needs to go to asynchronous non-blocking. It does. But it doesn't have to expose that as callback chains or promises to the whole over-arching infrastructure that sits on top. Concurrency units should be isolated from each other and internally execute whatever their logic is without having to worry about being polluted with callbacks. Then there could be multiple of such concurrency units executing in parallel but that is a the job of a decent VM/runtime/library to handle. > And at these levels of concurrency, you can’t go creating threads for every connection. Even something as simple as python gevent can create tens of thousands of green threads without a problem without exposing callback chains for everyone to see. Erlang VM and something like https://github.com/puniverse/quasar https://github.com/puniverse/quasar can run with millions of concurrency units so do goroutines and Rust's concurrency units (sorry forgot the name). > So the whole codepath needs to be non-blocking and async, not just the IO layer. Quite the opposite. If your whole codepath riddled with callback chains and your project is large now you have a huge headache to deal with. > This is where Node excels. If it forces one to use promises/deferreds/futures or nested callbacks, I say it fails.
- matt_heimer 13y ago"But there’s one thing we can all agree on: At high levels of concurrency (thousands of connections) your server needs to go to asynchronous non-blocking." No, we can't all agree on that. Asynchronous non-blocking might be better in limited scenarios where threads are expensive (memory or cpu or other constraints). "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." Sad to see so much work go into a faulty design. Take a look at this presentation http://www.slideshare.net/e456/tyma-paulmultithreaded1 http://www.slideshare.net/e456/tyma-paulmultithreaded1.
- _pmf_ 13y agoWhat makes bullshit articles more common than valuable articles? It's all about being a self-educated asshat with a lot of ego and second-order ignorance.
- manishsharan 13y agoI wish the author had considered middleware components written with Netty -- they are async and highly concurent as well. Moreover, Servlet 3.1 Specification , which is a part of Java EE7, includes JSR-340 Non-blocking I/O. In a typical application , ServletOutputStream and InputStream do read/write in a while loop while holding on to the request thread. This issue is potentially resolved in Servet 3.1 by adding event listeners – ReadListener and WriteListener interfaces. These are then registered using ServletInputStream.setReadListener and ServletOutputStream.setWriteListener. The listeners have callback methods that are invoked when the content is available to be read or can be written without blocking. The new versions of Glassfish and Tomcat servers already support Servlet 3.1. So Java already supports async style web applications. The programmers have to brush up their skills.
- zinxq 13y agoJava 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 http://www.slideshare.net/e456/tyma-paulmultithreaded1
- kasey_junk 13y agoYou 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.
- sheetjs 13y ago> Over 50k modules all written in the async style, ready to use Is this even true? There are "57 210" modules in NPM at the moment but many of them are explicitly synchronous
- programminggeek 13y agoNode 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.
- deleted 13y ago[deleted]
- lemmsjid 13y agoOne 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.
- uname1 13y agoRelevant: http://vertx.io/ http://vertx.io/ Polyglot, async, actor-like concurrent JVM platform.
- smellelderberry 13y agoNode.js has linear speedup over multiple cores for web servers, no other language can claim that.
- drdaeman 13y agoExcuse me, but you've mistyped the word "any" in "any other language" part. Last time I checked, event loops and async IO wasn't anything Node had monopoly on. In fact, those are available on every non-toy general purpose platform I remember off my head.