
Node.js cures cancer - kfalter
http://blog.brianbeck.com/post/node-js-cures-cancer
======
pilif
While node is doing the calculation, it won't be doing anything else (like
serving the next request). If a more traditional server is doing the
calculation, it will spin up another process to handle the next request.

If all you do is calculating Fibonacci, you can get ~(amount of CPUs) times
the performance. You could use multinode for the same effect, but this is
additional work.

In the end, it's a matter of the type of service you are doing. If it's a
Fibonacci generator, you'd use something that's better suited than either
node/JS or any other scripting language.

If you are doing something that's I/O heavy (which is probably the majority of
today's web applications), node or other scripting languages might be better
suited because they are easier to work with for most of us.

It's just tools. Not religion. I wouldn't use a hammer to remove a screw. And
I definitely wouldn't write hateful articles (I'm referring to the original
one) because somebody was using a screwdriver instead of a hammer to remove
the screw.

~~~
pshc
It's a troll article, but I'd like to point out that the "UNIX way" is alive
and well in node.js. I spawn new processes to do heavy lifting (e.g.
thumbnailing, hashing files) all the time. I put jobs into queues in redis and
handle them in other node processes. Obviously in co-operative multitasking
it's wrong to block the rest of the server.

~~~
pork
> Obviously in co-operative multitasking it's wrong to block the rest of the
> server.

I think that obviousness is exactly what the author missed.

------
piccadilly
The original Node.JS is cancer article is a silly troll.

But it's totally ridiculous how in response, people keep writing these
terrible, straw-man Python servers to try to prove that Python is so horribly
slow.

If you want to write Python web apps, there is a correct way to do it, and it
isn't to use SimpleHTTPServer. Write a WSGI application, and serve it with any
of a number of decent WSGI servers (just for starters, try uwsgi behind nginx;
but if you really insist on directly serving requests out of a server written
in an interpreted language, you could try gevent).

------
kenneth_reitz
It should be noted that, with PyPy, the Python example executes in 3.924s.

~~~
th_yc
Yes, since PyPy (and Rubinius) have JITs (like V8), that is the fairer
comparison. Nevertheless this highlights just how helpful JITs can be for cpu-
bound code -- makes me wish PyPy was more ubiquitous (and gets py3k support
sooner rather than later).

------
LeafStorm

        try:
            my_var
        except NameError:
            pass
        else:
            if my_var is not None:
                # Ted needs better examples
                ...
    

When would you _EVER_ need to use this code? There is no situation in which
you should ever need to use a variable in Python that may or may not be
defined. While Ted's example may seem like a cheap shot, it does highlight an
important problem with JavaScript: all the craziness with regards to types
that aren't "real" types like undefined, arguments, and Array.

~~~
wyuenho
I was thinking about the same thing. There's no auto-vivification in Python.
Thing just blow up and you fix your code. You _NEVER_ do this in real Python
code. I'm tired of straw man examples...

------
rian
IMHO i think node.js sucks because it forces you to manually pass callbacks
around. can't it remember my call site for me and use coroutines or call/cc or
yield or something? even fork() exists on UNIX (or pthread_create()). why is
passing callbacks around the answer? it's like using GOTO.

~~~
dbattaglia
It's painful but I can see why they don't want to be touching the V8 engine
itself (as tempting as it probably is). Short of doing that you are stuck
doing things the old-fashioned way (that is, callbacks).

I'm sure things will be a lot better if/when the V8 engine supports let/yield.

------
thatdrew
As a cancer survivor, just wanted to let you know that the poor taste
exhibited here is pretty sad. When you want to make your point next time, use
a title that doesn't include something that kills people. Thank you.

~~~
nasmorn
Like, node is the bomb?

I am sure cancer sucks more than anything I had to experience but the world is
not going to change its figures of speach for you and it is not directly
derogatory at all it just reminds you of your misfortune.

Btw I am not criticizing you for asking the OP to change his headline I just
think it is an impossible crusade.

~~~
nasmorn
See how I just typed crusade and pressed send without thinking.

------
petercooper
It's the equivalent of tying a giant boulder to the back of a Ferrari 599 and
scoffing at how Ferrari can dare to call it a "high performance" car. Stop
trying to drag giant boulders around.

~~~
no_other_alias
Not really. It's like saying "this ferrari doesn't need fuel!". Which is just
bullshit.

------
mjijackson
It's not the main point of the article, but I just thought I'd point out that
node already does have a WSGI/Rack-style library for folks who like that kind
of thing. It's called Strata (<http://stratajs.org>). Disclaimer: I'm the
author.

~~~
exogen
Thanks, I didn't know that. I've added a link to the article.

------
mschalle
I think one thing that the article hints at is still relevant: "developers"
nowadays throw around terms like "scalability" and other hype phrases and
think that since they know the slightest thing about some new technology,
they're a real developer. Sadly, this is incredibly naive. Any script kiddie /
code monkey can some application in the latest over-hyped framework and say
"HEY LOOK, IT CAN HAS NOSQL, IT CAN HAS SCALABILITY, IT DOES BIGGGGDATA", and
write some inefficient code for this application. The truth is that many don't
even understand basic data structures and how a computer processes information
at a lower level. If you don't understand what something such as algorithmic
complexity is, and can't look at your code from a more scientific and critical
point of view, don't call yourself a freaking developer. Pick up a book and
learn what REAL computer science is, not what the latest and greatest over-
hyped framework is called.

------
wyuenho
Is it just me or is Brian Beck misunderstood Python idioms? What's with the
try/except block? There's no auto-vivification in Python. So you just don't
try to catch a NameError. You just let it blow up in your test and fix your
code afterwards. I'm really tired of these straw man examples.

------
billconan
The article uses two examples to demonstrate that v8 is in fact fast. However,
when using python or ruby to create a web server, the server will actually run
in parallel (multiple threads), therefore, the average waiting time could be
less than the node.js version.

~~~
billconan
suppose, for example, we have two people connecting to the server at the same
time. if it is the node.js server, one person waited for 5 seconds, the other
one waited for 10 seconds, the average waiting time is (5+10) / 2 = 7.5

assume that the python server is less efficient, which takes 7 seconds to
finish the job. but it runs in parallel. so both two people waited 7 seconds.

therefore, on average, the python server is in fact, faster

~~~
billconan
i am not a node.js expert. one thing i am wondering is that, modern computers
have more than just one core. how node.js utilizes these multiple cores?

~~~
ricardobeat
By starting multiple processes.

See cluster (<https://github.com/LearnBoost/cluster>), fugue
(<https://github.com/pgte/fugue>), multi-node
(<https://github.com/kriszyp/multi-node>)

~~~
aliem
This is true for Python, Ruby, PHP. (I can't see ted's issues with node other
than misunderstanding of the framework's runtime)

------
robgleeson
I read your benchmarks on Ruby, but you didn't list the implementation or
version of Ruby you used.

I'd guess you used MRI 1.8.X.

I decided to benchmark other versions(and implementations) of Ruby.

= jruby 1.6.4 (7.3 seconds)

    
    
          user     system      total        real
      7.388000   0.000000   7.388000 (  7.349000)
    

= Rubinius 1.2.4 (Little under 6 seconds)

    
    
       user     system      total        real
      5.940015   0.006878   5.946893 (  5.842485)
    

= CRuby 1.9.2 (38 seconds)

    
    
          user     system      total        real
     38.250000   0.090000  38.340000 ( 38.376857)
    

= CRuby 1.8.7 (Little under 137 seconds)

    
    
          user     system      total        real
      136.960000   0.240000 137.200000 (137.437748)
    

Thanks!

~~~
th_yc
Exactly -- for a fair comparision, V8 (which has a JIT) should be compared
against Rubinius (for Ruby) and PyPy (for Python), which will both be nearly
as fast as V8.

Of course, it is true that V8 is ubiquitous, whereas Rubinius and PyPy are not
-- that is the one majore advantage of javascript.

------
pfarrell
Node has a mantra which addresses this whole thread, right back to the
beginning. "Everything in node runs in parallel, except your code". Manuel
Kiessling has a written a great tutorial (<http://nodebeginner.org>) that
shows how node noobs enter and can escape the blocking pitfall. Node is the
right tool when your requests block on I/O. I'm not convinced about CPU heavy
apps, yet.

------
sannysanoff
I wonder if

1) node.js async i/o is any different from haskell i/o? 2) author knows
something about strongly-typed languages, or he deliberately banned them those
from server side? Imho, dziuba tried to drop a hint about strongly-typed
languages, not python or ruby.

------
evanlong
guys guys guys. you do realize ted is trolling us all right (go look at his
twitter @dozba right now. I think he is having a great time). he is a pro at
this ([http://teddziuba.com/2011/07/the-craigslist-reverse-
programm...](http://teddziuba.com/2011/07/the-craigslist-reverse-programmer-
troll.html))

Also if his thoughts on node.js don't annoy you enough go take a look at his
archive: <http://teddziuba.com/archives.html>. He blogs/trolls/thinks about
NoSQL, OS X, twisted/tornado, python, queues and more.

~~~
jjm
Those new to NodeJS will still read this trolled post and find real gems of
info here. So all is not lost.

~~~
aaronblohowiak
Except it contains a lot of FUD, like saying that Node has no SSL support.

------
jufo
The nice thing about node (or any other event-based platform) is that
memoizing the Fibonacci function is trivial, whereas in a multi-threaded
implementation it would be tricky and error-prone.

------
kqueue
This is where gcd can help.
<http://en.wikipedia.org/wiki/Grand_Central_Dispatch>

------
dewiz
I just hope you will never have to experience what cancer is, otherwise you
will understand how important a "cure" could be.

------
ricardobeat
I'm getting 0.020s tops for that fibonacci code on node (time curl
<http://localhost/>), even going up to `1.1210238130165696e+167` (800th
number). OSX Lion on a C2d 2.3ghz.

Python 2.7.1 took 1m25.259s (no server).

Am I doing something wrong? Or is there some incredibly optimized code path
for OSX?

edit: even weirder, `time node fibonacci.js` without a server takes 0.090s.

~~~
exogen
Sure you're calling fibonacci(40) and not just defining the function?

~~~
ricardobeat
Yes. Turns out that the recursion overhead in python is huge, it can get down
to <100ms too with a non-recursive function.

~~~
piccadilly
I have no idea whether that is true and I'm not arguing with it.

Why are you writing web request handlers containing heavily recursive code,
and why do you seem to think that indicates anything meaningful about Python?

Please tell me you are not also using SimpleHTTPServer to try to prove points
about Python's performance (like <http://joshuakehn.com/2011/10/3/Diagnosis-
No-Cancer.html> and <http://blog.brianbeck.com/post/node-js-cures-cancer>)

~~~
ricardobeat
I wasn't. I was just curious about the huge difference in performance. These
numbers are from printing to console, no servers.

    
    
        def fibonacci(n):
            t = [0, 1]
            for i in xrange(n):
                t.append(t[-1] + t[-2])
            return t[-2]
        
        print fibonacci(800)

~~~
th_yc
Technically the above is a dynamic programming algorithm, in that you are
avoiding the recomputation of fib(1..n-1) in each step. That is equivalent to
recursion+memoization, which would perform roughly similar to the above. So it
is not that "recursion" is so dramatically slower than "iteration" in general,
it's just that for these kinds of computations, recursion should be memoized.

------
tedjdziuba
I like how every rebuttal turns into "how fast can you compute a fibonacci
number". I was looking for a function that burned a nontrivial amount of CPU,
the choice of fibonacci was arbitrary. Let's move on from that.

What I was showing was that if your request handler does a nontrivial amount
of CPU work, it will hold up the event loop and kill any "scalability" you
think you're getting from Node.

If you Node guys were really that irritated by this, you're going to be super
pissed when you learn how computers work.

I ain't even mad.

~~~
zohebv
Node is an asynchronous programming framework bundled with a largely async
library. If you have 40 cores on your system, you would presumably run 40
instances of node for a CPU intensive webserver(using multinode etc). So the
event handler won't get stuck as long as there are available cores.

What about a single core system? Well I guess a threaded/multi-process
solution would time slice the fibonacci requests between two threads so that
both requests are served in 10 seconds, instead of one request in 5 seconds
and the next one in 10 seconds like the node.js solution. Does not sound much
better.

If you have done any kind of systems programming, you would know that
availability of asynchronous I/O is a life saver, and can simplify your
locking model greatly. 90% of the issues you face when building such systems
is that some module deep inside grabbed a lock and issued a blocking I/O
request and now the rest of the system is bottle necked behind it. Node.js is
basically trying to eliminate the possibility of the existence of such a
module. This complicates the issue of I/O calls, but simplifies locking in the
sense that you don't really need all those locks in your system. In node.js of
course there are no locks. The complexity moves from reasoning about locks to
reasoning about correctly handling I/O calls and responses. IMO, this is the
correct place to move the complexity to, because locks are simply an
abstraction the programmer built. When debugging the system, we have to deal
with - "How to get rid of this monolithic lock", when the real problem is -
"This IO is taking too long we shouldn't be blocking on it". An async
programming framework tackles this problem head on.

If you use Python/Perl you will never really know the number of instances of
the process to run, Too many and you time slice requests, slow down all of
them, increase your queueing buffers instead of just dropping the extra
requests. Too few processes and you start dropping requests that you could
have served. With a framework like node.js the number of instances you want is
equal to the number of cores on the server.

Of course node.js can be an inappropriate solution for a wide variety of
reasons, but I could not find anything really relevant regarding that in your
post. Alex Payne discusses some issues here. You may want to read it.
<http://al3x.net/2010/07/27/node.html>

~~~
ittayd
The point of the original article is that there's no point in avoiding
blocking on IO while allowing blocking on CPU.

Furthermore, since node.js is single threaded, what's wrong with blocking on
IO in that single thread? The process hangs, is put to sleep by the OS and
wakes when there's IO available. You gain a simpler model of programming than
using callbacks/continuations

~~~
christkv
Most web applications are io bound not cpu bound as they spend most of their
time talking to other systems across the network like your db or queue or some
rest service. the cost of spinning up threads is memory and context switches
by the os. Async is just a way to avoid this for io operations. Node.js is
just an incredibly convenient way of doing this as there are less ways of
shooting yourself in the foot than if you apply the async patterns to other
tech platforms.

Cpu bound is still cpu bound on any tech platform and needs another strategy
to deal with it. I think it's better to look at node.js as a tool in your
toolbox that is well adapted to running high load web-services and apps that
are io bound instead of a swiss army-knife that does everything great.

But as any toolbox you need more tools in the box to be a good carpenter. That
includes picking tech that can do the cpu bound stuff in a appropriate manner,
be it java, scala, c++, erlang whatever. You don't write a graph database in
node.js unless you are masochistic. Just as you hopefully don't write an async
server in assembly.

From my usage perspective node.js is great for my async needs and the low
resource usage means I need less hardware to scale my typical web app.

~~~
wyuenho
True, but wouldn't just making IO async be enough?

~~~
christkv
Yes it would and in fact most language platforms have async io. It's just
harder to keep your yourself from introducing blocking calls in your event
loop as they come with mostly blocking libs :)

------
dewiz
how do you dare ?

and why are you at the top ?

really disappointed

~~~
dewiz
I'd really like to know why people like to joke on cancer and downvote people
which might be hurt by these stupid titles.

------
ryanpers
dboza is pretty awesome, beck didnt really address the underlying issue. If
you have any real computation, node.js is not your solution. I figured out
this in event-driven IO back when I was in school 15 years ago fffffff

