Node is Async by Default

The whole crux of Node.js is that everything is done async by default – you fire off something now and get a callback at some later time.  Its a beautiful paradigm and means that you can get great performance, because it fits so closely with the underlying operating system calls [ libevent, completion ports, sockets etc. ]

However, there are times you do need to enforce serial processing… for example checking for valid user/password must return a result before getting sensitive data and displaying it on the web page.

There are now sophisticated serial modules for Node, which Id recommend you look at for real work.  For example Conductor can mark sequential dependencies and will allow the most async processing to happen, while honoring those sequential constraints – the best of both worlds.  Another nice approach is this fork() primitive via stackoverflow.com.

Lets have a look at the simplest case, to see whats under the hood…

Demo Code

I made a test program to compare sync versus async,  This illustrates a very direct approach for serial processing using a queue of work functions. Code on github, here : async_vs_serial.js

For those of us new to Node, its useful to look at the simplest serial implementation.

There are three slow functions : do_aaa(), do_bbb(), do_ccc().  These can be run serially or in parallel.

In the serial implementation I pop them off the front of the work queue and run each in turn.  For this to work, each work function calls next when its callback completes.

Sample Output

    Default run [ Async ]

        > time ./async_vs_serial.js async

        RUNNING ASYNC
        >aaa
        >bbb
        >ccc
        <bbb took 50ms
        <ccc took 120ms
        <aaa took 220ms

        real    0m0.325s
        user    0m0.090s
        sys 0m0.012s

    Serial run

        > time ./async_vs_serial.js serial

        RUNNING SERIAL
        >aaa
        <aaa took 220ms
        >bbb
        <bbb took 51ms
        >ccc
        <ccc took 120ms

        real    0m0.479s
        user    0m0.075s
        sys 0m0.011s

The async functions are nicely interleaved, saving wall time.

Reality is Async by default

I think its best to think async by default… after all the CPU can do a huge amount of work while its waiting for IO to complete.  Its no surprise were seeing a whole raft of realtime web apps being powered by Node.js.

For background, see Ryan Dahls talk notes on ‘doing IO differently