Live data from Hacker News

Node.js cures cancer

blog.brianbeck.com

91–99 of 99 posts

Re: Node.js cures cancer

#91
post #77

Earlier quoted context omitted.

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…

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

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

Re: Node.js cures cancer

#92

Earlier quoted context omitted.

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/pos…

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)

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.

Re: Node.js cures cancer

#93

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) u…

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.

Re: Node.js cures cancer

#94

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

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

Re: Node.js cures cancer

#95
post #89
post #76

Earlier quoted context omitted.

How is running 40 instances of node processes different from running 40 instances of a single threaded web server? How is running 40 instances of single threaded event loops better than running 10 instances of a process with 4 threads each? If you had a choice would you not rather have light-weight processes (threads) rather than actual processes because of lighter memory requirements? Threads are too hard to program…

> How is running 40 instances of node processes different from running 40 instances of a single threaded web server? 40 Instances of a single threaded webserver can block for I/O. If your webserver is 50% CPU bound this means that your CPU utilization is lower than in the case of a perfectly async system. You will serve fewer requests per second than an async framework. This is where the rule of thumb "no of threads…

@zohebv there are several errors in deduction here:

> a multithreaded environment eventually ends up introducing several blocking I/O functions

really? multi-threading and non blocking io are two separate tools and one doesn't have to choose one of them exclusively. they can be intertwined, boost::asio allows you to run a single async event processor on as many threads you want. all without doing any explicit locking. if you're averse to locking (which based on your experience seems to be the case) you're taking things too far by avoiding threads completely.

> You are basically asserting that async programming has no advantage over any other approach whatsoever

i don't think anyone's asserting that. the original argument made was - if all you have in one process is a tight loop dispatching non blocking io handlers then you can't handle computationally intensive tasks. of course, you can spawn 40 other process - but i don't like a model where that's your /only/ option. there are middle grounds and any system that discounts them is short sighted.

> Trying to say that async programming is useless

yet again. i don't see that being said anywhere.

> Node is an asynchronous programming framework bundled with a largely async library ... If you have done any kind of systems programming, you would know that availability of asynchronous I/O is a life saver

now, if you'd indulge me with my own escapades in logic and word play.

icing is sugar whipped in butter. if you have eaten any desert, you'd know that sugar is nice and tastes very sweet. thus, conclusively, irrevocably, icing is good and we shall eat nothing else.

Re: Node.js cures cancer

#96
post #95
post #89

Earlier quoted context omitted.

> How is running 40 instances of node processes different from running 40 instances of a single threaded web server? 40 Instances of a single threaded webserver can block for I/O. If your webserver is 50% CPU bound this means that your CPU utilization is lower than in the case of a perfectly async system. You will serve fewer requests per second than an async framework. This is where the rule of thumb "no of threads…

@zohebv there are several errors in deduction here: > a multithreaded environment eventually ends up introducing several blocking I/O functions really? multi-threading and non blocking io are two separate tools and one doesn't have to choose one of them exclusively. they can be intertwined, boost::asio allows you to run a single async event processor on as many threads you want. all without doing any explicit locking…

> @zohebv there are several errors in deduction here:

@ajd I would disagree with this statement very easily and very confidently.

> really

yes

> multi-threading and non blocking io are two separate tools

asio is a way of minimizing the number of threads in a system and extracting maximum performance.

> i don't think anyone's asserting that

It follows by logical deduction. There are only 3 possible criticisms of node.js 1. I need shared memory 2. I dislike Javascript 3. I dislike asio

Given that the cancer post doesn't make a big deal of 1 and 2. you are left with 3. And if you read his follow up post he is again complaining about "event-loop" programming. Yes he is indeed complaining about asio. asio necessarily introduces event loops.

There is only one reason to use multiple threads over multiple pre-started processes. You need the shared memory. You should still be able to pull off shared memory in node but it can be cumbersome. I am yet to see anyone complain about needing shared memory and hence disliking nodejs. Its either

1. "threads are robust for cpu bound workloads"

- which can be solved by simply launching as many nodejs processes as Python processes, though you only need to launch as many nodejs instances as cores if you are not interested in winning this argument.

2. "Don't force this programming model on me"

It is not forcing any programming model on you except that shared memory is harder. And yes you cannot acquire a lock and go off and do io. If you want to do that then you can, by piling up pending events in a queue, but the ugliness of the code will stick out easily. You might as well switch to Python/Java threads or whatsoever.

> of course, you can spawn 40 other process - but i don't like a model where that's your /only/ option

Can you describe the other options you want to try?

Check this out http://teddziuba.com/2011/10/straight-talk-on-event-loops.ht... He has broken down his own defense with his fancifully named "Theorem 2". If you do more IO than CPU then "use more threads". Except he doesn't give you the number of threads because he doesn't know how many. In fact, he cannot know. And this is why asio is a win.

Fact is on an n-core system if you launch n nodejs processes you are guaranteed one of the 4 hold true 1. You service all requests thrown at the system 2. You maximize the CPU utilization 3. You maximize I/O utilization 4. You maximize RAM utilization - "4. is some what pedantic"

i.e. it will extract the maximum possible performance from the hardware you throw at it. It is just a consequence of making sure all io is non blocking. With a threaded solution you will never get the number of threads right and you will end up with a server that cannot serve all requests even when it has spare CPU, spare I/O capacity and spare RAM. Maximizing CPU utilization implicitly assumes the absence of locks. If you use asio as well as locks CPU utilization will not be maximized. This is something that most of the "nodejs" critics don't understand or fail to appreciate.

Yes shared memory is harder to do in node, but erlang doesn't do shared memory, Python cannot do threads sensibly, Java cannot do coroutines, why dump hate on nodejs because it isn't an ideal environment for a solution that requires shared memory? Sure there are many problems that require shared memory. However 95% of webservers don't fall into this category.

Lastly ted's inexperience really shows here, he is only 27 years old and has a lot left to learn. To start with he can stop trying to school Ryan Dahl, who is someone who certainly knows his Computer Science and is making a valuable contribution to the community.

Lastly as a practical exercise, try to build (at least as a thought experiment) some web service that outperforms node using respected platforms such as Python and Ruby. asio is a technique for IO bound loads but node will do better than Ruby/Python even on CPU bound loads thanks to V8. An order of magnitude faster. I have said that you need to have n processes for n cores, but in practice it seems just one process turns out to be enough as loads tend to be io bound and V8 is typically 10 times faster than Ruby. And if you have coroutines event based programming is not hard at all. So yes people have discovered that one nodejs process has replaced their two dozen Ruby processes and is serving out twice as many requests from the same box and they are impressed. And they don't care about what Ted thinks.

As a footnote, of course, you can do shared memory within a single nodejs process(trivially true), but for pure CPU workloads Java/C++ would probably be a better option.

Re: Node.js cures cancer

#97
post #96
post #95

Earlier quoted context omitted.

@zohebv there are several errors in deduction here: > a multithreaded environment eventually ends up introducing several blocking I/O functions really? multi-threading and non blocking io are two separate tools and one doesn't have to choose one of them exclusively. they can be intertwined, boost::asio allows you to run a single async event processor on as many threads you want. all without doing any explicit locking…

> @zohebv there are several errors in deduction here: @ajd I would disagree with this statement very easily and very confidently. > really yes > multi-threading and non blocking io are two separate tools asio is a way of minimizing the number of threads in a system and extracting maximum performance. > i don't think anyone's asserting that It follows by logical deduction. There are only 3 possible criticisms of node.…

>>> a multithreaded environment eventually ends up introducing several blocking I/O functions

>> really?

> yes

ok.

> Can you describe the other options you want to try?

http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/exa.... See HTTP Server 1 to 4.

my issue with node is independent of the programming language. i came here neither to bury ted nor to praise him. i don't care what he has written now. i found his original article funny and thought that it had some truth in it. all the other "logical deductions" you're making, require axioms that you have and i don't. i don't know this ryan guy either but if he's made a system so many people (including yourself, who i admire sincerely) think so strongly about, he must be an all around great guy. good for him.

as for me and this discussion, if node=asio and threads=avoid in your world, so be it, i'm ok with that :)

> one nodejs process has replaced their two dozen Ruby processes and is serving out twice as many > requests from the same box and they are impressed

that says a lot about Ruby (with which i have absolutely no experience)

Re: Node.js cures cancer

#98
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.

Re: Node.js cures cancer

#99
post #97
post #96

Earlier quoted context omitted.

> @zohebv there are several errors in deduction here: @ajd I would disagree with this statement very easily and very confidently. > really yes > multi-threading and non blocking io are two separate tools asio is a way of minimizing the number of threads in a system and extracting maximum performance. > i don't think anyone's asserting that It follows by logical deduction. There are only 3 possible criticisms of node.…

>>> a multithreaded environment eventually ends up introducing several blocking I/O functions >> really? > yes ok. > Can you describe the other options you want to try? http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/exa... . See HTTP Server 1 to 4. my issue with node is independent of the programming language. i came here neither to bury ted nor to praise him. i don't care what he has written now. i found h…

As it so happens, I am now implementing a load balancing solution on the JVM using the hybrid technique you recommend, lots of threads and some asio coming soon. However asio support on the JVM is poor. You are correct, in that using asio does not preclude you from using threads and viceversa; while node.js does not let you use threads. Your argument is valid, but this is very different from the argument ted is making viz. a CPU bound task will make the server useless. This is demonstrably false, and ignores the fact that typical web workloads are io bound.

The C++ solution you posted is probably a hybrid solution as you described, but it has its own set of restrictions. The environment does not guarantee run time safety, functional programming support is poor and coroutine support is non-existent or weak(I noticed there is an unfinished Boost.coroutine library that must heavily depend on #include ). While node shuts out threads it enables other solutions more suitable for a heavily I/O bound server. I only want to draw attention to the fact that almost all solutions available today involve some kind of compromise and hybrid solutions are possible in almost all of them.

As for the "deductions", I thought that they were obvious. You need threads rather than processes, so that you can share memory and avoid the serialization/deserialization complexity when communicating between threads. Or less often, you need a more elaborate synchronization mechanism such as reader/writer locks. As for asio extracting maximum performance, I think I will be better off writing a blog post about it.

Post reply on HN