5 ms·
NodeJS has a handful of things that tend to get brought up. Callback soup and difficult error handling. Both are resolved by promises. Once you get the hang of
by ralusek 10y ago
NodeJS has a handful of things that tend to get brought up. Callback soup and difficult error handling. Both are resolved by promises. Once you get the hang of promises, you are capable of doing concurrent asynchronous tasks in a manner that would be significantly more difficult in any other language.
On top of that, NodeJS is very, very fast. Compared to Python or Ruby, straight computing is significantly faster, but that's not even where the meaningful gains come from. Because NodeJS is non-blocking, the core is IMMEDIATELY available to serve the next request once an asynchronous call is made (read from DB/Cache/HTTP call). Because of this, each core can serve thousands of simultaneous connections.
Because JS is single threaded, in order to take advantage of multi core hardware, you just run the cluster module to effectively launch a concurrent instance of your application for each core.
As far as the language itself, once I understood it, I loved it. At first, I thought it was terrible, but when I went to ES6 syntax, and fully groked how to write asynchronous code, it rocketed to my favorite language.
I started with Java, moved to Python, and although it took me a while to come around to JS, I would absolutely never go back.
- jcrites 10y ago> Once you get the hang of promises, you are capable of doing concurrent asynchronous tasks in a manner that would be significantly more difficult in any other language. What languages are you comparing against? It seems like asynchronous code is more difficult to write in NodeJS than in C#, Go, or Rust, and about the same as Java. I can write code in Java in a style similar to promises using ListenableFuture (Google Guava) or CompletableFuture (Java 8) [0]. I should also clarify that I don't think promises are the optimal approach to asynchronous code. I think you can do better, and the primitive "await" is an example of how. Bob Nystrom (munificient) wrote an article called "What Color is your Function?" [1] that does a good job describing the difficulties of promised-based async, and how await improves on it, and how Go does even better. (From what I've read, JavaScript ES8 is supposed to include async/await, and NodeJS seems to have support for them. At that point you'll be able to program in standard JavaScript and use await, which will bring NodeJS up to parity with the first-tier languages.) > On top of that, NodeJS is very, very fast. Compared to Python or Ruby, Perhaps that's true compared to Python and Ruby, but not when compared to other high-performance runtimes like Java. The following three paragraphs are from a comment I previously wrote on this topic [2]. Folks might also be interested in the TechEmpower web framework benchmark [3]. The top Java entry ("rapidoid") is #2 on the benchmark and achieves 99.9% of the performance of the #1 entry (ulib in C++). These frameworks both achieve about 6.9 million requests per second. The top Java Netty server (widely deployed async/NIO server) is about 50% of that, while the Java Jetty server, which is regular synchronous socket code, clocks in at 10% of the best or 710,000 R/s. NodeJS manages 320,000 R/s which is 4.6% of the best. In other words, performance-focused async Java achieves 20x, regular asynchronous Java achieves 10x, and boring old synchronous Jetty is still 2x better than NodeJS throughput. NodeJS does a pretty good job given that it's interpreted/JITed while Java is compiled, though Lua with an Nginx frontend can manage about 4x more. NodeJS is handicapped by having to orchestrate everything from its single thread. I agree that asynchronous execution can provide an advantage, but it's not the only factor to consider while evaluating performance. If throughput is someone's goal, then NodeJS is not the best platform due to its concurrency and interpreter handicap. If you value performance then you'll chose another platform that offers magnitude better requests-per-second throughput, such as C++, Java, Rust, or Go according to [3] and [4]. But I'll grant it has better IO performance than many other dynamically typed languages. Asynchronous execution also does not necessarily require explicit async programming. Other languages have as good or better async support -- for example, see C#'s `await` keyword. [1] explores async in JavaScript, await in C#, as well as Go, and makes the case that Go handles async most elegantly of those options. Java has Quasar, which allows you to write regular code that runs as fibers [5]. The code is completely normal blocking code, but the Quasar runtime handles running it asynchronously with high concurrency and M:N threading (similar to Go). Plus these fibers can interoperate with regular threads. Pretty gnarly stuff (but requires bytecode tampering). If async is your preference over Quasar's sync, then Akka might be up your alley instead [6]. Lastly, high performance servers don't necessarily require asynchronous code at the application layer; performance sensitive logic can often live in the library or framework e.g. Netty, reverse proxy e.g. Nginx, or in the OS's context switching. > Because NodeJS is non-blocking, the core is IMMEDIATELY available to serve the next request once an asynchronous call is made (read from DB/Cache/HTTP call). Because of this, each core can serve thousands of simultaneous connections. This also describes regular synchronous code with many threads. Once your application makes a blocking call, the operating system context switches to another thread (process). This is how boring old blocking Java code running on Jetty outperforms NodeJS in request-per-second benchmarks [3]. And you could take advantage of this in NodeJS too if it weren't for the fact that JavaScript execution occurs in a single thread! For most typical applications, overall performance is more influenced by the efficiency of the runtime than it is by the concurrency/async strategy. [0] https://github.com/google/guava/wiki/ListenableFutureExplained https://github.com/google/guava/wiki/ListenableFutureExplain... and https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html https://docs.oracle.com/javase/8/docs/api/java/util/concurre... [1] http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y... [2] https://news.ycombinator.com/item?id=12341886 https://news.ycombinator.com/item?id=12341886 [3] https://www.techempower.com/benchmarks/#section=data-r11&hw=peak&test=plaintext https://www.techempower.com/benchmarks/#section=data-r11&hw=... [4] https://news.ycombinator.com/item?id=12268988 https://news.ycombinator.com/item?id=12268988 [5] http://docs.paralleluniverse.co/quasar/ http://docs.paralleluniverse.co/quasar/ [6] http://akka.io/ http://akka.io/
- lod723 10y ago> Once you get the hang of promises, you are capable of doing concurrent asynchronous tasks in a manner that would be significantly more difficult in any other language. FYI, anyone who has worked with Elixir or Erlang views these sort of statements about Node as completely ridiculous. The only languages right now that are making a serious effort to bring real concurrency to modern programming are Go and Elixir. Node with its single threadedness and global heap doesn't come close, since those are fundamental problems with JS. The papering over the defienct language concepts with attempts like promises don't address these issues at all.
- ralusek 10y agoFor concurrent asynchronous tasks, being single threaded or multithreaded shouldn't make any meaningful difference. To make a million concurrent asynchronous calls on a single thread takes couple MS, to make on multiple threads takes about the same. For concurrent SYNCHRONOUS tasks, being single threaded or multithreaded makes a huge difference, but that's not what we're talking about here. It's also not at all fair to call NodeJS single-threaded in regards to its concurrency model, as it utilizes all cores through parallel application instances.
- lod723 10y agoThe multiprocess Node concurrency model is brittle and fault intolerant. The event loop scan actually has real bottlenecks at a certain level of fds in flight. A real scheduler really wins here; libuv sits below the knowledge of the runtime to really be optimal. You become CPU bound far sooner than you expect. With a global heap, you also become memory bound far sooner than you expect as well.
- chrisco255 10y agoYour typical Node instance is using an order of magnitude less memory than the beastly JVM. We use Java microservices with Spring at my job and each "micro" service consumes close to 1GB of memory. I've never written a Node service that had more than 100MB footprint.
- domlebo70 10y agoIs this satire? I can't tell anymore.
- Jean-Philipe 10y ago> you are capable of doing concurrent asynchronous tasks in a manner that would be significantly more difficult in any other language. "any other language" is a bold claim. I heard Haskell gets concurrency more elegantly, or Erlang.
- dragonwriter 10y ago> Once you get the hang of promises, you are capable of doing concurrent asynchronous tasks in a manner that would be significantly more difficult in any other language. Of the top of my head, concurrent asynchronous tasks are simpler in Pony, Go, Erlang, Elixir, Haskell, and Oz than in JS (and these generally also handle parallelism beyond "run another instance of your app", too); and lots of other languages have concurrency constructs equivalent to JS promises (and, often, also async/await), so JS is at best no easier than that larger group.
- int_19h 10y agoWhat language doesn't have promises these days?
- uranian 10y ago> Once you get the hang of promises, .then( you realize it's just a callback..
- amalantony06 10y agoLove this. This is precisely why I love Javascript too, I find these douchey condescending comments on Javascript/Node.js from people who've not grasped the language and it's philosophy deeply, extremely annoying. There's a lot a capable developer can accomplish with Javascript, with it's first order functions, collection operations, generators, promises and now, async /await. Granted JS is not idiot-proof, but I'd any day use a powerful language than a highly restricting one (think Java and Go).
- lawik 10y agoOr maybe they just don't share the philosophy. Or are opposed to it. A lot of Node enthusiasts also come across as douchey and condescending as they claim that people just haven't grasped the language or its philosophy. I think Node is absolutely fine. But I see why someone who values robustness and error-reduction as primary goals or someone that has a firm grasp on other asynchronous models might not see many advantages to Node. Just as some people value stability higher than progress, neither is necessarily evil, just beliefs. People have different priorities and Node delivers on some and is not geared towards others. But I don't find Nodes async, single thread model very interesting or revolutionary. It is very pragmatic and definitely useful but I found the Erlang VM and Elixir a much more compelling solution for example.
- amalantony06 10y agoHey, more power to you if you want to use more expressive/functional languages than Javascript like Erlang or Clojure. However claiming that a language that allows nothing beyond the Object oriented model of computation like Java or Go is more robust or allows you to have less errors would not be accurate (see the comments above). The primary reason anyone would use Javscript over say Erlang would be the ubiquity of the language and the availability of libraries or strong familiarity with the language. But my point is Javascript provides you the tools to write functional code that is robust (if you are disciplined) and generators + promises (and async/await) makes the single threaded async model painless. I certainly did not claim that it was a silver bullet or a revolutionary model of computation.