Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient closure structure in node.js

I'm starting to write a server in node.js and wondering whether or not I'm doing things the right way...

Basically my structure is like the following pseudocode:

function processStatus(file, data, status) {
...
}

function gotDBInfo(dbInfo) {
    var myFile = dbInfo.file;
    function gotFileInfo(fileInfo) {
        var contents = fileInfo.contents;
        function sentMessage(status) {
            processStatus(myFile, contents, status);
        }
        sendMessage(myFile.name + contents, sentMessage);
    }
    checkFile(myFile, gotFileInfo);
}
checkDB(query, gotDBInfo);

In general, I'm wondering if this is the right way to code for node.js, and more specifically:

1) Is the VM smart enough to run "concurrently" (i.e. switch contexts) between each callback to not get hung up with lots of connected clients?

2) When garbage collection is run, will it clear the memory completely if the last callback (processStatus) finished?

like image 860
davidkomer Avatar asked Mar 15 '26 05:03

davidkomer


1 Answers

  1. Node.js is event-based, all codes are basically handlers of events. The V8 engine will execute-to-end any synchronous code in the handler and then process the next event.

    Async call (network/file IO) will post an event to another thread to do the blocking IO (that's in libev libeio AFAIK, I may be wrong on this). Your app can then handle other clients. When the IO task is done, an event is fired and your callback function is called upon.

    Here's an example of aync call flow, simulating a Node app handling a client request:

    onRequest(req, res) {
        // we have to do some IO and CPU intensive task before responding the client
    
        asyncCall(function callback1() {
            // callback1() trigger after asyncCall() done it's part
            // *note that some other code might have been executed in between*
    
            moreAsyncCall(function callback2(data) {
                // callback2() trigger after moreAsyncCall() done it's part
                // note that some other code might have been executed in between
    
                // res is in scope thanks to closure
                res.end(data);
    
                // callback2() returns here, Node can execute other code
                // the client should receive a response
                // the TCP connection may be kept alive though
            });
    
            // callback1() returns here, Node can execute other code
            // we could have done the processing of asyncCall() synchronously 
            // in callback1(), but that would block for too long 
            // so we used moreAsyncCall() to *yield to other code*
            // this is kind of like cooperative scheduling
        });
    
        // tasks are scheduled by calling asyncCall()
        // onRequest() returns here, Node can execute other code
    }
    
  2. When V8 does not have enough memory, it will do garbage collection. It knows whether a chunk of memory is reachable by live JavaScript object. I'm not sure if it will aggressively clean up memory upon reaching end of function.

References:

This Google I/O presentation discussed the GC mechanism of Chrome (hence V8).

http://platformjs.wordpress.com/2010/11/24/node-js-under-the-hood/

http://blog.zenika.com/index.php?post/2011/04/10/NodeJS

like image 88
leesei Avatar answered Mar 17 '26 18:03

leesei



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!