Node.js is Backwards
blog.ankurgoyal.com
blog.ankurgoyal.com
Unless you write your own Objective-C http server and run it on Mac OS X Server (it's not that hard, I've done it), this isn't very useful for Web programming. However, if you're comparing the languages / frameworks themselves (you can use all three to code command line tools, for example), GCD becomes a very seductive option.
GCD works by throwing code blocks (obj-c closures) into queues, and letting the runtime do its magic. You can have it execute code synchronously, asynchronously, or in parallel.
GCD will optimize and distribute your blocks the the available CPU cores. You can even enumerate using blocks, and instead of doing loop iterations one by one, it'll distribute them to the cores in parallel.
[1]: http://en.wikipedia.org/wiki/Grand_Central_Dispatch [2]: http://developer.apple.com/library/ios/#documentation/cocoa/...
The distributed enumeration sounds interesting, could you point me in the direction of where I can find some more info about that?
http://developer.apple.com/library/mac/#documentation/Darwin...
People tend to lump Node and Erlang together because they both avoid shared-state concurrency. But they're completely opposite approaches: Erlang has concurrency but no shared state. Node has shared state but no concurrency.
Not that you'd get this from the article.
NodeJS is great for applications with a lot of clients, but not for CPU intensive apps. That's why I predict similar technologies built on Erlang, Scala, and Go will have more longevity than NodeJS.
Well, you do with node what you do with anything: if you have 4 CPU cores, run 4 copies of your app. Problem solved.
Node's first commit:
commit 9d7895c567e8f38abfff35da1b6d6d6a0a06f9aa
Author: Ryan <ry@tinyclouds.org>
Date: Mon Feb 16 01:02:00 2009 +0100
add dependencies
How old is Erlang? 25 years or so?> What happened to this?
There's been some preliminary stuff on giving spawned node processes a more slick API, with the intent of then being able to optimize them in some way.
Whether or not it'll end up at the WebWorker API is yet to be seen, but that'd certainly fit with node's "don't reinvent BOM conventions where they fit" pattern.
I had no trouble understanding the paragraph that you complain about and found the article to be very well written.
Where do you see excessive jargon or convolution?
Calling node.js concurrent obscures the important fact under discussion: namely that it won't scale beyond one CPU in a world where 8-core servers are routine.
In essence, concurrency has to do with systemsy stuff- how to do things that might overlap without causing problems (race conditions). On the other hand, parallelism is about breaking a problem into smaller parts and attacking it in pieces. The problem with most languages is that they require the programmer to worry about both at the same time; however, languages like Erlang alleviate most of these problems, the biggest of which is shared state.
Rewriting language via blog posts doesn't work (c.f. "hacker"). Doing so as a way to, frankly, cover up a huge design flaw in your favorite library just seems dumb to me.
Still, given the way Node forces programmers to manually unravel tasks and write everything as callbacks, I'm not inclined to call it "concurrency" even if eg. the processing of a group of web requests overlap in wall-clock time.
But how's Node.js "backwards"?
It seems to me that the author has picked on one statement by one individual, and turned that into a link-bait.
There's a lot of research surrounding CPS-transformed code (look at Orbit (http://people.csail.mit.edu/riastradh/t/adams86orbit.pdf), for example), but nobody ever needed to manage it by hand.
For a more meaningful comparison between Node and Erlang, look at how they handle errors.
This is what I thinking when reading all the discussions about Node.js (mainly here, at HN).
Disclaimer: I don't program in JS, and I won't touch it without six feet pole (read: code generator from some higher-level strongly-typed language).
By "actor-like way" here I just mean a code module ("actor") sees one thread (at a time), and the runtime takes care of the details of scheduling threads when a module has an event/message/request to process. Also I guess avoiding callbacks. But you could be more Erlang-ish/Akka-ish in more details if you wanted.
node.js punts this to the app developer to instead run a herd of processes. In most cases that's probably fine, but in theory with one process and many threads, the runtime can do a better job saturating the CPU cores because it can move actors among the threads rather than waiting for the single-threaded process an actor happens to be in to become free. The practical situations where this comes up, I admit, are probably not that numerous as long as you never use blocking IO and are basically IO-bound. (Only CPU-intensive stuff would cause a problem.)
btw this has been hashed out to death on the node.js list: http://groups.google.com/group/nodejs/browse_thread/thread/c...
http://stackoverflow.com/questions/4493001/good-use-case-for...
http://fornax-sculptor.blogspot.com/2010/08/eda-akka-as-even...
(minimal code example)
http://groups.google.com/group/akka-user/browse_thread/threa...
There's probably similar cookbook examples and benchmark/ overhead per process measurements for F# MailboxProcessors, if you're curious
When I found that Stackless Python didn't have a way to read/write on multiple channels at once I was quite shocked.
http://hackage.haskell.org/packages/archive/stm/2.1.1.2/doc/...
http://www.haskell.org/ghc/docs/7.0.2/html/libraries/base-4....
It also looks that "select" statement could be done in a combinator library way.
The power of Haskell (or of any proper modern language) isn't in the language itself, it's in the number of things you can express as a library, on top of the language.
Could someone familiar with Erlang please clarify:
"To understand why this is misleading, we need to go over some background information. Erlang popularized the concept of lightweight processes (Actors) and provides a runtime that beautifully abstracts the concurrency details away from the programmer. You can spawn as many Erlang processes as you need and focus on the code that functionally declares their communication. Behind the scenes, the VM launches enough kernel threads to match your system (usually one per CPU) "
In common Unix tools like 'ps' and 'top' the term 'Lightweight Process' is used as a synonym for OS thread, eg, the LWP column in 'ps -eLf' shows the thread ID.
In this article, LWPs seem to be different from threads? Is this correct? If they're not threads, what are they?
Lulz? Here's a much simpler explanation: it's a polling server. It's not an intentional approximation of this or that (Erlang), this is just how event loops using select\poll\epoll\kqueue have always worked. Unless you want to do a bunch of extra work and throw in per-core preforking\threading and scrap the libev dependency Node built upon.
Ted Dziuba explained this well for Python http://teddziuba.com/2010/02/eventlet-asynchronous-io-for-g....
You're referring to is coroutine vs. continuation passing (callback). This is unrelated to whether you also are also forking into a small number of processes for each core. You can do both. Node simply doesn't yet. Nginx with workers is an example of an asynchronous server that does.
In regards to your link and the coroutine yielding approach: Being able to write psuedoblocking and monkeypatching code is not necessarily a good thing! It encourages you to keep making subrequests sequentially in serial, rather than in parallel as comes natural with using callbacks. It also discourages one from using custom continuation logic such as quorums. Examples of when the yielding approach fails:
- You want to both send and read independently on the same connection without creating multiple coroutines\greenthreads\userthreads per connection.
- You want to continue once 2 of 3 data services have calledback that information was successfully stored
I've written a fast single-core asynchronous server here in Lua without using user space thread yielding that you may be interested in: https://github.com/davidhollander/ox
However, I don't think the inability of current JavaScript to do async I/O without callbacks is Node's biggest problem. As others have said, it works for smaller projects (and even has some geek appeal). And as Havoc Pennington and Dave Herman have explained, generators (which are coming with ECMAScript Harmony) and promises will eventually provide a very nice solution. So Node has a path to grow out of the callback model without giving up its single threaded paradigm.
http://blog.ometer.com/2010/11/28/a-sequential-actor-like-ap...
http://blog.mozilla.com/dherman/2011/03/11/who-says-javascri...
The bigger problem (which I don't see getting solved anywhere down the road) is the lack of preemptive scheduling, which is available in Erlang or on the JVM. What you see under high load with Node is that latency is spread almost linearly over a very wide spectrum, from very fast to very slow, whereas response times on a preemptively scheduled platform are much more uniform.
http://jlouisramblings.blogspot.com/2010/12/differences-betw...
And no, this is something that can't be solved by distributing load over multiple CPU cores. This is problem really manifests itself within each core, and it is a direct consequence of Node's single threaded execution model. If anybody knows how to solve this without resorting to some kind of preemptive threading I'd be very curious to hear about it.
What are some good web libraries for Erlang?
Webmachine, "A REST-based system for building web applications": https://bitbucket.org/justin/webmachine/wiki/Home
See also: http://www.google.com/search?sourceid=chrome&ie=UTF-8...
You have mochiweb ( https://github.com/mochi/mochiweb ) and misultin ( https://github.com/ostinelli/misultin ) if you want something a bit more like node
This is like saying "This Honda Civic clearly sucks compared to my helicopter. Let me write you an article about everything that my helicopter does betting that your Civic". Clearly the Civic was build for another purpose and so the comparison is void.
This is a blanket statement that perhaps displays the author's opinion on Javascript as a language itself.
What are these benefits? Are they really exclusive to Node? (or if not exclusive, then vastly simpler with Node)
It's a distributed pub-sub engine, so one client can publish an event, and the others on the server will receive it. Probably about half the code is shared between the server and client. That means less bugs and easier maintenance.
Technically there are tools that will convert, say, Haskell to Javascript so that you can have shared code between a client and server. In practice, I don't know anyone who does that. I'm sure for most it feels like a bit of a hack. So for practical purposes, the only way to share code between the client and server is by using javascript (or coffeescript) on the server-side as well. Node.js IMO is the best server-side javascript engine.
Instead, the examples of shared code in Node are always simple utility functions, validators and the like. While it helps not to have to rewrite those, it's not groundbreaking. Facilitating the sharing of state between client and server -- hopefully irrespective of the server-side language -- would be a much better goal, IMO.
I agree that JS-on-server is a nicer way to share code than compiling other languages into JS.
-No mental context switch when working on both ends
-Easier serialization (though JSON is pretty portable...)
-Sharing code
They aren't exclusive to Node and JS, but browsers run JS and will continue to for the foreseeable future. Since the front end can't budge its language at the moment, the back end has to.Seriously? A very common problem in web apps is validation logic is usually duplicated in JS and Server side language.
Node allows the same logic to be used in both cases. These are not a 'few little functions'. Validation is a central part of most business applications.
Given the potential to template html with javascript, and to code exclusively in javascript. You could end up with webapps written entirely in one language.
Whether that is a good thing or not remains to be seen, but it is something that we should pay attention to.
For example, validating a user's name on the client merely checks if the name's length is in a certain range and doesn't contain invalid characters. On the server it requires a query to the database -- possibly more.
I also reject the notion that there is a significant context switch involved in going from one language to the other.
The functionality implemented is mutually exclusive. This canard needs to die.
Also I appreciate you picking up where I left off, I've been making a major lifestyle change and am almost completely sapped of energy.
This has improved my concision considerably wrt code and conversation.
Cheers, let me know if you find yourself in SF, I'll get you a round on me.
Math (significant math), encoding and hashing being done on the client sounds like a poorly designed application. Same for templating on the server -- which I assume you mean manually compiling templates using a library, and sending the result to a client, perhaps as a property of a JSON object.
Sorry, but what is that supposed to mean?
The functionality on either end of a client/server application is usually not "mutually exclusive". They're two sides of the same coin and could indeed benefit tremendously from code sharing. Just because the potential has barely been realized so far doesn't mean it doesn't exist.
Like what? I hear this argument all the time, but it's always unsubstantiated.
In my experience, the choice of language is less important than the programmer's understanding of facts that have little to do with the language itself.
If you are developing client-side browser code, for instance, then you have little choice but to use Javascript.
But learning JavaScript is not the hard part: mainstream programming languages, in and of themselves, are rarely difficult to master.
On the contrary, the skill that separates the superior engineers from the inferior ones is the mastery of the environment that the program operates in.
For front-end developers, it is an intricate understanding of how browsers work (i.e., the DOM and supported events) and some good understanding of how to optimize requests back to the server. (There is probably much more they know than this, but I'm not a front-end developer.)
Similarly, back-end developers have much to learn about how to efficiently and reliably serve (hopefully) many thousands of requests per second. They need to understand the limitations of their servers, how to manage memory and storage effectively, and build reliable, operable services.
For both types, these skills often take many years to master, and they are hardly interchangeable. Consider that developers themselves often describe themselves as "front-end" and "back-end" people. The fact that you can now use JavaScript on the server side does little to disturb this reality; and things wouldn't change much if you could run Perl or Python or Ruby in the browser tomorrow.
Have you ever done it? It's very comfortable. It reduces one element of friction in the daily thought-work of the programmer.
By the same token, a comfortable chair or nice text editor won't turn an amateur into an all-star programmer in the absence the other important stuff (smarts, work, etc.) It can be a huge waste of time to fret over your editor or your chair adjustments. But that's not going to make me less likely to sit in a nice ergonomic chair and use vim rather than notepad.
Comfort isn't everything, but it's certainly not nothing.
At work, every time we undertake a project in Node, it just doesn't work at scale, and it has to get re-implemented in Erlang.
A lot of this is for personnel reasons. To all of us Node is a neat new toy, where a few engineers are Erlang wizards. If Node crashes we don't have any experience debugging it. If it locks up there's little intuition why.
Can people point to examples of large production Node deployments?