
Node.js is Backwards - ankrgyl
http://blog.ankurgoyal.com/post/6433642218/node-js-is-backwards
======
SeoxyS
Speaking of concurrent programming and parallelism. If you're not into
functional programming, check out Apple's Grand Central Dispatch[1] and
Objective-C Blocks[2].

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/...](http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxGettingStarted.html#//apple_ref/doc/uid/TP40007502-CH7-SW1)

~~~
bittersweet
I've been hacking away on Obj-C and more specifically MacRuby and did some
basic stuff with GCD already, using the async queueing system.

The distributed enumeration sounds interesting, could you point me in the
direction of where I can find some more info about that?

~~~
SeoxyS
You might wanna take a look at dispatch_apply with striding:

[http://developer.apple.com/library/mac/#documentation/Darwin...](http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/dispatch_apply.3.html)

------
cwp
What a bunch of gobbledygook.

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.

~~~
m0th87
Node _does_ have concurrency. It does not have parallelism. This is an
important distinction:
[http://stackoverflow.com/questions/1050222/concurrency-vs-
pa...](http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-
what-is-the-difference)

~~~
edtechre
The article is not "gobbledygook". A well known limitation of NodeJS is its
lack of support for parallelism. You have to try to take advantage of
parallelism of the OS itself by pre-forking the Node server.

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.

~~~
jrockway
_NodeJS is great for applications with a lot of clients, but not for CPU
intensive apps._

Well, you do with node what you do with anything: if you have 4 CPU cores, run
4 copies of your app. Problem solved.

~~~
thesz
Imagine your app has 16GiB of precomputed tables in memory...

~~~
strmpnk
Node.js has a heap size limit. One of the biggest weaknesses IMO well before
people complain about CPU cores.

------
arturadib
OK fine, Duncan might not have chosen the best words when comparing Node to
Erlang.

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.

~~~
silentbicycle
Having to manage callback control flow _by hand_.

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.

------
thesz
Article is quite refreshing, given booming Node.js popularity.

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).

------
bitcoins
My node.js project spreads all node.js i/o across multiple node processes ( in
machine, network, or browser ) and creates a distributed EventEmitter across
all nodes.

<https://github.com/Marak/hook.io>

~~~
peregrine
Where were you 4 months ago?

------
hp
It would be pretty simple conceptually (maybe not practically) to make node.js
work in an actor-like way, here's a piece of toy code I wrote that does it for
JS (not node, but no reason the same couldn't be done for node):
[http://blog.ometer.com/2010/11/28/a-sequential-actor-like-
ap...](http://blog.ometer.com/2010/11/28/a-sequential-actor-like-api-for-
server-side-javascript/)

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://groups.google.com/group/nodejs/browse_thread/thread/c334947643c80968/564816670e56cdab)

------
pkulak
Does anyone know how well Scala can handle the requirements of a typical
Node.js project? IE, thousands of network connections and rather light CPU
load overall? Can Scala be a Node.js or Erlang replacement?

~~~
gtani
look at some of the Akka deploys

[http://stackoverflow.com/questions/4493001/good-use-case-
for...](http://stackoverflow.com/questions/4493001/good-use-case-for-akka)

[http://fornax-sculptor.blogspot.com/2010/08/eda-akka-as-
even...](http://fornax-sculptor.blogspot.com/2010/08/eda-akka-as-
eventbus.html)

(minimal code example)

[http://groups.google.com/group/akka-
user/browse_thread/threa...](http://groups.google.com/group/akka-
user/browse_thread/thread/6e10174ac8bd9c4f?pli=1)

There's probably similar cookbook examples and benchmark/ overhead per process
measurements for F# MailboxProcessors, if you're curious

------
skybrian
Sure, it's the reverse of goroutines, which allow you to do easy asynchronous
programming using synchronous code.

~~~
jamwt
.. or erlang processes. Or python greenlets. Or Haskell forkIO threads. Or
libcoroutines.. Etc.

See: <http://news.ycombinator.com/item?id=1549023>

~~~
uriel
Erlang has a slightly different but largely equivalent model, but the other
alternatives you mention lack Go's channels and/or the select construct which
is one of the greatest things about the language.

When I found that Stackless Python didn't have a way to read/write on multiple
channels at once I was quite shocked.

~~~
thesz
How's that Haskell lacks channels?

[http://hackage.haskell.org/packages/archive/stm/2.1.1.2/doc/...](http://hackage.haskell.org/packages/archive/stm/2.1.1.2/doc/html/Control-
Concurrent-STM-TChan.html)

[http://www.haskell.org/ghc/docs/7.0.2/html/libraries/base-4....](http://www.haskell.org/ghc/docs/7.0.2/html/libraries/base-4.3.1.0/Control-
Concurrent-Chan.html)

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.

------
mikemaccana
_Edit_ : looks as if Erlang does indeed have its own, separate definition for
lightweight process. See the disambiguation page on
<http://en.wikipedia.org/wiki/Light-weight_process>. How very poor of whoever
started misusing an existing concurrency term to refer to something else - as
if discussing these matters isn't already difficult enough.

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?

------
davidhollander
> _Node.js’s concurrency mechanisms are simply an approximation of Erlang’s._

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.

~~~
ankrgyl
Erlang, and other similar efforts like Haskell's forkIO and Python's
eventlet/gevent, are also built upon the same fundamentals as libev (and some
actually just use libev). But using libev in the way that Node.js does boils
down to user-space threads with cooperative scheduling (you yield control
every time you make a blocking I/O call). The abstractions that
Erlang/Haskell/Python provide let you program in the familiar synchronous,
threaded style while retaining the performance advantages of an explicit
(e)polling server.

Ted Dziuba explained this well for Python
[http://teddziuba.com/2010/02/eventlet-asynchronous-io-
for-g....](http://teddziuba.com/2010/02/eventlet-asynchronous-io-for-g.html)

~~~
davidhollander
> _(you yield control every time you make a blocking I/O call)_

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>

------
hannesw
I think the opinions expressed in this article are valid.

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.ometer.com/2010/11/28/a-sequential-actor-like-api-for-
server-side-javascript/)

[http://blog.mozilla.com/dherman/2011/03/11/who-says-
javascri...](http://blog.mozilla.com/dherman/2011/03/11/who-says-javascript-
io-has-to-be-ugly/)

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...](http://jlouisramblings.blogspot.com/2010/12/differences-between-
nodejs-and-erlang_14.html)

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.

------
dreamdu5t
It seems like most people are using nodejs for the web, and nodejs includes a
library for HTTP.

What are some good web libraries for Erlang?

~~~
superrad
Nitrogen is well equipped web framework <http://nitrogenproject.com/>

You have mochiweb ( <https://github.com/mochi/mochiweb> ) and misultin (
<https://github.com/ostinelli/misultin> ) if you want something a bit more
like node

------
dscape
Very well written article summarizing some discussions that are apparently
common in the erlang community.

------
m0th87
Suggesting Node and Erlang have the same concurrency model is a complete
pigeonholing. CPS != Actors.

------
Khao
I've read a lot about Node and watched Ryan Dahl's introduction to Node and
maybe the author of this post should have done that too. At no moment does
Ryan talks about Erlang and having anything to do with Erlang's way of
thinking. Node was built to use javascript's awesome V8 engine and its event
loop that many people already know and love to provide evented IO. I love Node
and I think it is a great project, which has nothing to envy about Erlang.

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.

------
aufreak3
It looks to me like all this debate has no observable consequence on the
respective programming communities. Node folks will program the Node way and
love it and Erlang folks will program the Erlang way and love it. The creators
of neither are trying to woo the other and they perfectly well understand
_operationally_ where each system stands.

------
mattking
> Node.js appeals to people who already know Javascript and don’t want to
> learn a new language

This is a blanket statement that perhaps displays the author's opinion on
Javascript as a language itself.

~~~
premchai21
I don't see how it does. Making note of the entrenchment bonus granted by a
language already known by much of the target audience isn't necessarily making
a value statement about the bonus or secondary effects thereof.

------
jamesaduncan
Fair catch, I could have chosen more precise words.

------
Sym3tri
Uh oh. Cue flame war.

------
alnayyir
I've been saying this about Erlang and Node for awhile, and I don't know
anybody who knows both Erlang and JS that takes Node seriously.

~~~
m0th87
I know both and I take Node seriously. Using the same language at both the
client and server end has some serious benefits. And web servers are mostly
shared-none, so not having first-class support for communication between Node
processes is not that big of a deal. Node has its niche.

~~~
jessedhillon
> _Using the same language at both the client and server end has some serious
> benefits._

What are these benefits? Are they really exclusive to Node? (or if not
exclusive, then vastly simpler with Node)

~~~
m0th87
Here's a case study: an open source project I made with node.js;
<https://github.com/node-bus/node-bus>

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.

~~~
jessedhillon
I looked through your shared/util.js and, while I don't want to take anything
away from your project, it doesn't seem to me that there is much of a case for
_significant and useful_ code sharing in Node. When I think of code sharing, I
expect something like Luna, from Asana <http://asana.com/luna/>

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.

~~~
seoguru
have a look at dnode: <https://github.com/substack/dnode> bidirectional remote
method invocation. Oh, and a complimentary robot free of charge:
<http://substack.net/browse/2010-11-08%2022:16:39> :-)

