11 ms·
Many are forgetting the initial reason node.js became popular. Consider the popular server-side landscape before node.js. It was dominated by Java, Python, et
by bit_logic 9y ago
Many are forgetting the initial reason node.js became popular. Consider the popular server-side landscape before node.js. It was dominated by Java, Python, etc. The primary way these ecosystems handle concurrency is OS-level threading. There was nothing else in the popular languages. Each language had some niche library that did non-blocking I/O (Twisted for Python, Netty for Java), but these all had a critical flaw, which is the rest of the ecosystem didn't support it. Basically every library, almost all existing code used the threading model. And when you mix threaded libraries with a non-blocking I/O server, it completely falls apart because the threaded code blocks.
Then came node.js. Look at the ecosystem it came into. JS itself has very little standard library, and nothing for I/O. It has a highly optimized VM supported by the resources of Google. It's a language known by many developers. node.js took this well developed clean slate and built a non-blocking I/O server on top of it. It offered a concurrency model on the server side that's completely new to many developers, an alternative to the traditional threading model everyone knew. Since server-side JS didn't exist yet, it forced all libraries to be written in this non-blocking way. Every package in NPM is written to support the core design of node.js which is non-blocking I/O. And it was exciting to many developers, it was a reason to rewrite everything in this new way.
- k__ 9y agoWas it? I had the feeling before Node.js, everything was PHP.
- disordinary 9y agoMost things are still PHP thanks to Wordpress.
- thehardsphere 9y agoThey're both appealing to "web developers" of relatively less experience for similar reasons.
- valarauca1 9y agoEach language had some niche library that did non-blocking I/O [...] Netty for Java) Non-blocking IO has been in java standard library since 1.4 More then Netty supported it. Netty, Jetty, Dropwizard, Grizzly, VERTX. Apache Tomcat supported non-blocking IO 5 years ago.
- _pmf_ 9y agoTo recap for the non-Java reader: the problem was that the Servlet specification did not initially support suspending and resuming without suspending and resuming the thread handling the request. The Servlet 3.0 specification supports it, but before you could not use multiplexed IO within containers that required the servlet interface, even though IO multiplexing worked perfectly fine (and, as you said, some containers allowed it via a custom interface, since it is pretty much trivial to add).
- cmiles74 9y agoI think the only new thing that node.js brought to the table was a nice way to run Javascript on the server. Node.js doesn't use threads, but as you said, their event-driven non-blocking I/O model wasn't new (Python had Twisted and Java had Netty). In addition, Java has had non-blocking I/O (in the form of the nio) packages for quite some time. In my opinion, Node.js became popular because people wanted to run Javascript in a server environment.
- sporkland 9y agoI remember distinctly at the time that the fact that there was excitement around node.js because it was built from the ground up to use evented IO exclusively. All the libraries, the core runtime etc. People in other languages (C) were for sure doing it, but not in the holistic way node was. As opposed to java and python where you needed to avoid using the library calls that were blocking.
- cmiles74 9y agoFair enough, I agree that Node.js uses the evented model (AFAIK) almost exclusively. Still, the evented model is not unique to Node.js nor did they invent it. In my opinion, it was the dedication of Javascript developers and their reluctance to use another language that popularized this model: they had no choice.
- sporkland 9y agoYeah. Ryan Dahl was pretty clear at the time that he was inspired by people using C and achieving really high connection counts on single machines. So he for sure was inspired by others, and obviously built off the same foundations in the kernel. At some point Isomorphic Javascript became the main reason to use it, as golang has largely stolen the non-blocking IO crown with its implementation of green threads.
- z3t4 9y agoYou can write JavaScript in classic ASP, there are many server JavaScript, but they are serial/blocking, and NodeJS is async/non blocking.
- gazaren 9y agoIMO, the biggest reason Node.js got popular was because of JavaScript. You just need to learn one language to do full stack development. No need to deal with Python or Java or whatever. Being single-threaded is a side effect of using V8, which is mostly single-threaded. Since you only have one thread, you need IO to be non-blocking.
- jrs95 9y agoYeah, I think this is the primary reason it really had traction. There was definitely some initial hype around async and performance, but there are a lot of ways (especially now) to achieve that without Node. The real win for me is a familiar language with a huge community and package ecosystem on the server that you likely have to use anyways in the browser.
- kitd 9y agoAgreed. And if it had just stayed at JS and Node, I wouldn't have minded. But then they had to go and inflict NPM on the world, and what should have been a tidy stack got idiotically messy.
- rmrfrmrf 9y agoI disagree because Rhino and Narwhal were already around. Libuv and the event/callback approach to IO (which is the part that's familiar to front-end devs) are the secret sauce to Node.js.
- nulagrithom 9y agoOn that note, coming back from node.js has been a really frustrating experience for me. I want to scream every time somebody suggests threading as a solution to non-blocking database calls and HTTP requests. It's made me painfully aware of how often parallelism is suggested in place concurrency. C# in particular does a great job at conflating concurrency and parallelism. Both fall under the same Task namespace and it drives me mad to no end. I've also seen a couple instances of Execute and ExecuteAsync both blocking because the underlying driver didn't support async, with no indication other than my async calls blocking. It's quite different from the async-by-default sort of thing that's going on in the node.js world.
- cdelsolar 9y agobut why? Go's model is perfect. They're not real threads, it's basically very similar to Node, except that you can write code without a mess of callbacks and it's easier to reason about...
- stouset 9y agoGo's model doesn't even statically prevent data races (as Rust's does). You might think Go's model is good, but it's a far cry from perfect. Although I'll be happy to point out why Go's model isn't even good. Go's lack of ability to perform meaningful abstraction combined with the low level of its concurrency primitives means you end up having to copy/paste and slightly tweak dozens of lines of flow-control logic every time you use them. This[1] is an excellent critique of Go's concurrency model. [1]: https://gist.github.com/kachayev/21e7fe149bc5ae0bd878#so-what-about-patterns https://gist.github.com/kachayev/21e7fe149bc5ae0bd878#so-wha...
- a13n 9y agoasync await though
- paulddraper 9y agoAnd no shared-memory CPU parallelism.
- turtlebits 9y agoAs a Python/Ruby web dev, exactly this. Dealing with uwsgi/passenger was so painful to me. And asyncio in python3 still boggles me.
- 52-6F-62 9y agoI like Python a lot, and use it for a number of things even though my position doesn't require it where I work, but uwsgi was the thing that kept steering me away from it. I'll probably make myself master it at some point, but it just felt fumbling at first take and left a bad taste.
- sreque 9y agoNode.js brings callback hell to the serverside world of threads and we're supposed to be grateful? It's like you don't know the history of computing. Callback-based code was the original programming model in UNIX dating back decades! Threaded code came about because it's far easier to write it than callback-based code. The ONLY reason to do callback-based code is for performance reasons: for network-IO-heavy apps there is less OS-level overhead from managing thousands of connections with a few threads using the OS-provided non-blocking I/O operations than managing a connection per thread. Even then, if you actually want to do better than connection-per-thread, you have to avoid the POSIX API for non-blocking I/O and use whatever OS-specific API is available for better performance (epoll, kqueue, or completion ports). The greatest joke of all though is that Node.js is dirt slow because Javascript is dirt-slow. Yes, you may be able to invent some microbenchmark where Node.js looks good, but the only reason it does in that benchmark is because the Node.js app is spending 99.9% of it's time executing code in a C library. Any real-world Node.js app is going to be slow because Javascript in general, even on V8, is anywhere from 10-100x slower than C or even well-written Java. And worst of all, Node.js is single-threaded! If you want to scale onto all your cores you have to go multi-process, which is an incredible pain in the general case. So, you switch to a runtime and framework that forces a more difficult way of programming on you (callback hell) but which is better for general networking performance, but you use a dirt-slow, single-threaded runtime while doing so. You are basically ending up with the worst of both worlds, and any decent development team will run circles around you in performance and productivity with just about any other backend stack.
- tmp124567 9y agoYou don't know what you are talking about. Code some simple server on c using epoll I think you could learn a lot from that. And JS has async await now, so no callbacks.
- sreque 9y agoI have written servers in C with epoll that were used in production, thank you. And yes, I'm aware of async/await and its limitations. State-machine-style transformations from blocking-looking code to non-blocking code are definitely helpful, but in the end still fall short in terms of usability to a full blocking style of programming. To even begin to approach the ease-of-use of blocking-style programming you need something akin to delimited continuations in your programming language.
- corford 9y ago>because the threaded code blocks. Python and Java threads don't block on I/O, only on CPU. Event loops (i.e. node) also block on CPU. AFAIK, node's advantage over threads was just that it offered much higher concurrency for I/O constrained tasks for the same memory (and was easier to programme for people coming from the front-end world).
- int_19h 9y agoPython and Java threads block the thread on I/O. Which is wasteful, because you have a huge chunk of memory allocated for the stack of that thread, being reserved but not actually in use.
- corford 9y agoYep, hence node's advantage of offering much higher concurrency for the same memory usage.
- tmp124567 9y agoThis. I'am allways surprised by the amount of developers that don't understand the difference between threads, epoll-select and forking and io bound vs cpu bound.
- gshulegaard 9y ago> Many are forgetting the initial reason node.js became popular. Consider the popular server-side landscape before node.js. It was dominated by Java, Python, etc. The primary way these ecosystems handle concurrency is OS-level threading. There was nothing else in the popular languages. What? I am sorry but this is not true. Coroutines have been a concept for...well a long time: https://en.wikipedia.org/wiki/Coroutine https://en.wikipedia.org/wiki/Coroutine Green threads also have been around for a while. > but these all had a critical flaw, which is the rest of the ecosystem didn't support it. Basically every library, almost all existing code used the threading model. And when you mix threaded libraries with a non-blocking I/O server, it completely falls apart because the threaded code blocks. I am not sure how you can say this while using Python as an example. Python has the GIL which, typically viewed as a limitation, actually prevents the situation your assertion suggests. In fact, one of the largest barriers to removing the GIL is the wealth of libraries and C-extensions to Python that implicitly rely on the thread safety guarantees/limitations of the GIL (as covered by Larry Hastings as part of his first Gilectomy talk). To be clear, there are reasons Node became popular, but let's not pretend that it brought some sort of concurrency revolution to the "server-side landscape" in 2009. Edit: Heck, NGINX was an asynchronous, event driven web engine released in 2004 and written in C: https://en.wikipedia.org/wiki/Nginx https://en.wikipedia.org/wiki/Nginx
- AgentME 9y ago>Coroutines have been a concept for...well a long time: ... Green threads also have been around for a while. What web frameworks were built around using them? Was there a good ecosystem of libraries that were easy to use with the web framework without introducing blocking I/O? >I am not sure how you can say this while using Python as an example. Python has the GIL which, typically viewed as a limitation, actually prevents the situation your assertion suggests. In fact, one of the largest barriers to removing the GIL is the wealth of libraries and C-extensions to Python that implicitly rely on the thread safety guarantees/limitations of the GIL (as covered by Larry Hastings as part of his first Gilectomy talk). Aren't all python threads backed by OS threads? And pointing out that threading has been used by too many Python libraries to change supports the previous comment's assertion that non-blocking I/O was hard to use exclusively in languages like Python because too many libraries used blocking I/O. >Edit: Heck, NGINX was an asynchronous, event driven web engine released in 2004 and written in C: Nginx is pretty specialized. Not really sure it's useful to compare it to a programming language / web framework with an ecosystem of compatible libraries like PHP, Ruby on Rails, django, nodejs, etc.
- jdc0589 9y ago> Since server-side JS didn't exist yet, I'm being petty, but serverside JS did exist before node (e.g. Narwhal, which I believe is where jsgi and a lot of the commonjs stuff originated)
- pawelk 9y agoThere was also Rhino in the Java land (I remember working with Helma before Node came out), JScript on IIS, some projects embedding SpiderMonkey. I think node.js finally made server-side JS take off because 1) it was based on V8 which was the new, performance-oriented JS engine powering Chrome, and 2) it was self-contained (i.e. didn't rely on Java on one hand, wasn't just a scripting layer of something larger on the other).
- icedchai 9y agoServer side JS is older than that. It existed over 20 years ago. Does anyone remember Netscape Livewire? It was basically "ASP-style" server-side javascript that ran on Netscape's "Enterprise" web server. It was a little unstable, but pretty advanced for the time (had DB connectivity, etc.)
- int_19h 9y agoWhile we're at it, ASP itself had JavaScript (well, JScript, technically) support alongside VBScript, out of the box. It wasn't particularly popular, probably because anyone doing ASP was likely to be using the rest of MS stack - and that meant VB for desktop LOB apps, usually.
- ori_b 9y agoOS-level threading is often pretty good -- you can usually fork and join tens of thousands of threads per second. (I believe that the initial NPTL benchmarks showed something like 20 microseconds for thread spawn.) It's not the tens of millions per second that you get with green threads, but thread creation has an unfair reputation of being slow. It was once true, but that was 20 years ago.
- endorphone 9y agoYou're getting a lot of pedantic replies, but your post is spot on. At the time it arrived, asynchronous operations were close to impossible in PHP, very difficult and awkward in .NET, and very uncommon in Java. In Node it not only was possible, it was impossible (without going to great efforts) to do otherwise. People have a short memory, but at the time getting single to double digits of requests per second on a beefy server was entirely typical. Yes, someone somewhere could demonstrate an alternative, but node completely changed what was normal. It was extremely high performance for the time.
- debaserab2 9y ago> People have a short memory, but at the time getting single to double digits of requests per second on a beefy server was entirely typical. Umm, what? It was not a challenge to get to double digits of requests per second on a beefy server in 2008, at least not in any popular language (including PHP and Ruby). It was (and still is) easy to scale requests of "blocking IO" languages by spawning additional threads at the server level.
- patrickthebold 9y agoAlong those lines: Has anyone seen benchmarks that show significant benefits for non-blocking IO?
- endorphone 9y agoI said entirely typical, not that it was a dick-sized "challenge". A completely standard developer on .NET or PHP in 2008 was building pages that rendered at less than 10 requests per second. This is experience, not a guess, given that my role was improving the performance of those disasters. A completely average developer on node was building pages that was 10x to 100x better performance. Secondly, simply spawning threads is laughably non scalable.
- noblethrasher 9y agoNot the OP, but I knew what you meant I soon as I read it. But, did the typical .NET app really not make use of the Asynchronous Programming Model that was part of the standard library? I ask because in 2008 I was only about 3 years into professional web development, and even I knew about stuff like the C10K problem[1] and that I/O Completion ports were apparently one of the few things that Unix people admired about Windows. [https://en.m.wikipedia.org/wiki/C10k_problem https://en.m.wikipedia.org/wiki/C10k_problem]
- InclinedPlane 9y agoYup. Node.js isn't quite as old as you make it out to be, there were plenty of mature tech stacks out there with PHP/Perl, Ruby, C#, etc. Many of them perfectly fine to work with. Node.js came along with a very different conceptualization of scalability relative to other web-servers, and that was what drew people to it. Today we have things like varnish, nginx, fast-cgi, etc. as well as much faster servers which make it a lot easier to scale out web stuff without having to redesign it from the ground-up, but node.js was for its time a hugely advantageous way to approach scaling. And it still is for many use cases, but today it's matured into something that has a lot more to offer.
- thehardsphere 9y agoNot to be a pedant, but all of the projects you mention in "today we have" pre-date Node and were commonly available.
- pdeuchler 9y agoErrrrr what? No, node.js became popular because it allowed the legions of front end devs to overnight become full stack devs without learning anything but a new framework. To a lesser extent it also provided an alternative to PHP in the "get a simple crud app up and running with minimal knowledge" space, but I think that's far dwarfed by the ability of front end devs to start leveraging their skills on the backend.
- lsdafjklsd 9y agoThere weren't really 'legions' of front end devs when node came out. People were just learning backbone.js and the idea of SPA's being viable was still forming. It was not easy to pick up if you were coming from something like rails, because it had no well documented complete framework solution. The people that were doing node in the early days were legit back end folks. I am now a front end developer, but I learned on rails and I remember having a hard time 'learning' node. It had no debugger (I was used to something like pry) and was generally a collection of 'low level' libraries.
- tantalor 9y agoForgetting? It's mentioned in the 2nd paragraph of the article, He showed us that we are doing I/O completely wrong and also taught us how to build software using pure async programming model
- lackbeard 9y agoYour claim is that Node was popular because people were excited about writing servers using 100% non-blocking I/O? I guess I agree that's a part of it but we should note that in 99.5% of those cases the servers would've performed better written in Java using blocking threads. I think the other parts of it are: 1) many people wanted to write server-side Javascript, 2) people did not want to use Java, and the concurrency stories for PHP, Ruby, and Python were (and still are) really crummy.
- mattschmulen 9y agoAll this and the developers that were driving new line of biz products were coming from the front end ( web and mobile ), of course all front ends need backends and when these these folks went looking they naturally leaned toward JavaScript the same language they were using on the front end and Async model