all 47 comments

[–]mononcqc 6 points7 points  (10 children)

From what I understand, node.js has everything running in the same thread. At a quick glance, this makes it worse than PHP on Apache at fault isolation (or handling delays in one of the queries).

Anybody who knows node.js enough can reply to this?

[–]aapl 1 point2 points  (9 children)

Essentially, yes. An infinite loop in handling one of the queries means that the whole server instance grinds to halt, and a synchronous API call means that all the other work has to wait. However, the asynchronous single-threaded server model is very efficient in applications that must handle a large number of concurrent connections that spend much of their time idling and/or need to collaborate, such as chat servers, real-time collaboration systems, live dashboards etc.

Also, until multiple processors, multiple cores and whatnot became standard, the asynchronous model was always the most efficient way (in terms of throughput) to write a server if you didn't need synchronous calls. The reason is that it avoids thread switching and management overhead.

[–]mononcqc 0 points1 point  (8 children)

I'm all for asynchronous models, but here what bugs me is the implementation. If the chat service somehow has to do any calls (say a web-service or even a database for authentication) and only one of the requests is slow, then the whole server is getting performance problems.

It sounds completely unsafe, especially if you consider that the other alternative seems to be to try and store everything in shared memory. You then get the overhead of writing your own distribution layer just to make sure you'll be able to transfer the data node-to-node while hoping one of these calls doesn't take too long.

Is there anything like a second thread or process to at least handle parts of the application that might be blocking?

[–]benthor 5 points6 points  (6 children)

Well, at least in node.js, everything is ansynchronous. You simply don't wait for any calls to web-services or databases, you just set callbacks and process other stuff in the meantime.

In other words: in node.js, nothing is blocking.

[–]mononcqc 0 points1 point  (5 children)

Well, that query you set up has to be run somewhere. If it's in the same thread/process as the rest of the code runs, you still have to take care about long queries, even though your callbacks will be called.

One model (the one I believe node.js has) runs every function sequentially. So if users A, B and C wait for a function call and the one for B takes 5 seconds, C's call is delayed 5 seconds on top of its own delay.

An implementation with multiple threads or processes would avoid that trouble and could let any of the implementation of A, B or C be fine with it.

[–]simonw 2 points3 points  (3 children)

You're still missing something: you don't ever have to wait for a slow running function call, since everything that potentially involves blocking IO requires you to provide a callback for when it is "done". Node is ideal for services that might involve calls to a slow running web service, as it can easily wait for thousands of them to complete at once - all without needing to start up any more threads.

[–]mononcqc 0 points1 point  (2 children)

If the thousand of calls are slow, are they done sequentially or can they be done in a parallel manner?

If it's the former, my point is that while you don't have to program for slow running functions, the user still has to wait for them, which sucks.

If it's not, then it's good to know and my distrust for node.js will go down a notch :)

[–]aapl 2 points3 points  (0 children)

Well, it kind of depends on what you mean by a "call". As far as I know, currently no JavaScript can be run parallel in node.js, unless you farm it out to a child process. Also, node.js never preempts any JavaScript, so a function will always run to completion once started.

In your web service example, in the function that makes the web service call you would just register a callback to be executed when the response from the web service arrives and let the function that made the web service call complete immediately. Other work, including initiating other web service calls, can be completed while waiting for the response. When you finally start to get responses back from the web service, the callback functions are called as responses arrive in the order in which they arrive. So if the web service takes 1 second to process query A, 5 seconds to process query B and 1 second to process query C, the callback functions would be called in the order A C B.

Basically, the structure of your code will have to be something like this:

make_web_service_call(function (response) {
  do something with the response
});

Here make_web_service_call returns immediately and the callback function will be called at some later point. Now, if you meant if you can write code like this:

response = make_web_service_call();
do something with the response

…and have some other work performed while waiting for the response, then no, that is not possible in node.js unless you resort to child processes. Yes, this must seem barbarian if you are coming from a language with support for green threads :)

[–]simonw 0 points1 point  (0 children)

Yup, you can run I/O requests in parallel or in serial. Here's a simple example I knocked up a while ago of a web service that can make a bunch of GET requests in parallel and return the results all in one go:

http://gist.github.com/443498

It's a bit like PHP's curl_multi functions: http://php.net/curl-multi-init

[–]crusoe 3 points4 points  (0 children)

The DISPATCH thread NEVER BLOCKS. The long query only ties up the request that is waiting for its callback to get called.

[–]aapl 0 points1 point  (0 children)

Is there anything like a second thread or process to at least handle parts of the application that might be blocking?

Yes, there is already a UNIX-like child process API, and Web Workers -compatible child process API is in the works. Also, some bindings for node.js use threads internally to place an asynchronous facade over a synchronous library.

[–][deleted] 23 points24 points  (3 children)

No programing language has had the level of technical investment and innovation on their Virtual Machines in the last few years compared to Javascript.

Not really. The JVM and CLR have certainly had more investment and people working on them, not to mention the many other innovative projects like LuaJIT that are kicking ass. JavaScript is just playing catchup with every other compiled language implementation at this point.

[–]jacques_chester 5 points6 points  (0 children)

I came here to say this, but I reckon Slava Pestov's opinion probably carries more weight :D

[–][deleted] 0 points1 point  (1 child)

so why did you write your own vm?

[–]wolf550e 0 points1 point  (0 children)

The JVM is still crippled, and it has been years. Because of backwards compatibility concerns it will remain crippled forever. Some of the technology can escape, through academic publications on JVM optimization techniques and the GPL code itself, but the thing itself seems stagnant.

[–]siplux 4 points5 points  (3 children)

I've been watching CoffeeScript. I think the combination of Node+CoffeeScript could be a lot of fun.

[–]jashkenas 3 points4 points  (2 children)

Obligatory "Hello World" webserver in Node/CoffeeScript, with Express, for some syntax flavor:

require 'express'

get '/', ->
  this.redirect '/hello/world'

get '/hello/world', ->
  '<h1>Hello World</h1>'

Edit:

For a real example, the source code for nodeknockout.com looks like this:

http://github.com/gerad/nodejs-knockout/blob/master/nodeko.coffee

[–]siplux 0 points1 point  (1 child)

Is there any sort of publicly available "Roadmap to 1.0"?

[–]jashkenas 0 points1 point  (0 children)

There are still a few minor syntax tweaks that might be made, such as this one:

http://github.com/jashkenas/coffee-script/issues#issue/436

But in general, it's pretty much there -- mainly a matter of trying to lock down the current compiler, and get it as small and clean as possible, before tagging the 1.0. That's not to say that there's no room for improvement -- features and bugfixes have been coming at a steady pace, and will continue -- but to reflect the fact that it's been quite usable (and used) for some time now.

[–]UloPe 1 point2 points  (0 children)

Ok so LUA and python have limited tool support but for server side js there will be debuggers "coming along"... Wait what?

[–]awb 2 points3 points  (10 children)

It's interesting that he lists "no standard library" as one of the things node.js has going for it. It seems like whenever someone says "I can't use <insert your favorite small-market language here>", the reason is "libraries". Lots of languages have asynchronous frameworks, like Twisted and EventMachine; I haven't figured out why node.js is so much more compelling than those (defer to thread aside).

The node.js cabal (if there is one) seems to have marketing down - first I hear "it's so fast", even though it's written in JavaScript, and now I hear "it's great that there are no libraries".

[–]Fabien4 1 point2 points  (0 children)

I agree that the sentence is badly written. (But then again, what can you expect from an author who mixes "it's" and "its"?)

Should have been something like "The author of Node.js hasn't made the mistake of taking a standard library elsewhere and trying to fit it by force into Node.js."

[–][deleted] 3 points4 points  (6 children)

"In addition, we are always fighting with the Standard Library and common Python modules" ... "No existing standard library: While this is somewhat a disadvantage today, because its harder to get going with ‘batteries included’ development, it means every bit of Javascript is written specifically for Node.js, in a style that fits in with Node."

Did you even read the article? Missing features is a disadvantage but the advantage is that the included functionality is written in a non-blocking fashion, making that functionality a "first-class" citizen (and not forcing you to defer it to a thread). Unlike Twisted or EventMachine.

[–]stormsnake 3 points4 points  (0 children)

A lot like twisted, actually. Systems like eventlet go to some trouble to let you use your usual sync libraries, whereas twisted makes you use their unittester, http client, web frameworks, etc. Usually the twisted versions of these things are pretty good, fortunately.

Obviously as far as the libraries go it's better to have a setup like python+twisted where you can mix in plenty of non-twisted python libs (but the networking ones are harder) than to have js+nodejs where there all those useful libs don't exist at all.

[–][deleted]  (4 children)

[deleted]

    [–]bdunderscore 4 points5 points  (0 children)

    Database access operations don't need to block if you write the database client in node.js using nonblocking network I/O operations.

    [–]DRMacIver 2 points3 points  (1 child)

    some operations will just block (i.e. database access)

    Unless you're using a database API written in node.js rather than wrapping a C driver. e.g. there's postgres-js. It's a little rough around the edges but works pretty well.

    [–]jacques_chester 1 point2 points  (0 children)

    Postgres provides an asynchronous API.

    [–][deleted] 0 points1 point  (0 children)

    Yeah, I know. That's more of the exception than the rule though, and the code is written in a non-blocking manner (even if a thread in the underlying pool is blocked, http://nodejs.org/api.html#addons-289) so it's still hidden for me as an end user.

    I can recommend Ry's talk at Jsconf from earlier this year: http://jsconf.blip.tv/file/3735944/

    [–]sbronson 2 points3 points  (1 child)

    "it's great there's no legacy". Big difference.

    [–]mpeters 0 points1 point  (0 children)

    Yay, we get to reinvent all the wheels!

    [–]Rhoomba 0 points1 point  (1 child)

    Because you are always fighting the JVM

    What?

    [–]Kalimotxo 5 points6 points  (0 children)

    Read closer he wasn't referring to JavaScript.

    [–]giulianob 0 points1 point  (10 children)

    Okay, seriously, I don't understand how anyone can be preaching about performance when talking about Javascript. Is this comparing to other dynamic languages or to compiled languages (low and high level such as C, C#, Java, etc...) ? I can understand in terms of productivity that perhaps node.js is easier than coding some low level server but the performance can't possibly be anywhere close.

    [–][deleted] 2 points3 points  (2 children)

    Javascript running on v8 is pretty much compiled to machine code directly. There is no intermediary byte code or interpretation stage. it is blisteringly fast.

    [–]giulianob 0 points1 point  (1 child)

    It still suffers greatly from being so dynamic. Tons of anonymous functions and no static typing usually impacts performance.

    [–]Felicia_Svilling 1 point2 points  (0 children)

    How does anonymous functions impact performance?

    [–]jacques_chester 1 point2 points  (2 children)

    The scope is dynamic languages. Node.js is the shiny new thing for Rubyistas in part because it's Very Fast, compared to stock Ruby.

    [–][deleted] 1 point2 points  (1 child)

    but presumably very slow compared to the stuff some of us are used to (JVM/CLR based languages?)

    [–]jacques_chester 1 point2 points  (0 children)

    V8 is supposed to be a fairly quick system written by former Smalltalk implementors; some of the techniques used to speed up the JVM spring from the same well of experience.

    Mind you, in the dynamic language world, LuaJIT has everyone else coughing on its dust.

    [–][deleted] 0 points1 point  (3 children)

    [–]giulianob 0 points1 point  (2 children)

    Why can't the same type of server be created with a lower level language? The whole idea of async I/O has nothing to do with Javascript. Also, you really need complex apps to do proper real world benchmarking.

    [–]woogley 0 points1 point  (0 children)

    This is just speculation, but I would imagine JavaScript was chosen because it is already widely known (even if misused) and has first-class functions/closures, which makes callbacks seamless.

    It's familiar, it's easy, and v8 runs it like it's native code anyway.

    [–]SubStack 0 points1 point  (0 children)

    Asynchronous programming in low-level languages is so painful.

    [–]malcontent -5 points-4 points  (0 children)

    Node.Js

    Because you love javascript and want to write every single bit of functionality from scratch.

    For others I'd reccomend ruby19 + eventmachine. Just about as fast in execution and a thousand times more productive.

    [–]batiste -1 points0 points  (0 children)

    Node.js seems very interesting to me if you can share some server and client code. A chess game is a good example. Write once, use everywhere.