Home > javascript, node.js, Programming > Node.js example 2: parallel processing

Node.js example 2: parallel processing

[ UPDATE 2/29/2012 ]
I just discovered a much better way to perform the same parallel processing task through the answer by Linus G Thiel to one of my stackoverflow questions.

        var async=require('async');
        // gen an integer between 1 and max
        function gen_rnd(max) {
                return Math.floor( (Math.random()*max+1)*1000 );
        }

        function job(lbl, cb) {
                console.log('Job %s started', lbl);
                console.time(lbl+'-timer');
                setTimeout( function() {
                        console.timeEnd(lbl+'-timer');
                        cb(null, lbl.toUpperCase());
                }, gen_rnd(5) );
        }

        console.time('all jobs');
        async.parallel([
                function(cb) { job('p1',cb) },
                function(cb) { job('p2',cb) }
        ], function(err, results) {
                console.log('do something else upon completion of p1 and p2');
                console.log('results=%j', results);
                console.timeEnd('all jobs');
        });

[ Original version of this post ]
I just wrote another example using Node.js to demonstrate the benefit of non-blocking io programming. In this example I need to do a job that depends on two processes p1() and p2(). Job won’t start until both p1 and p2 are finished. If I start p1 and p2 one by one, the total time used to do job would be at least T(p1)+T(p2). But if I can start p1 and p2 in parallel then the time required would be reduced to Max(T(p1), T(p2)). To make the simulation closer to real-life examples, the execution time for p1 or p2 would be anywhere between 1 and 6 seconds. So if you run this example you will see sometimes p1 is finished early, sometimes p2 is. The core part of this example uses event.Emitter.

Update 11/6/2011: using console.time and console.timeEnd to keep track of time consumed

var util=require('util');
var events=require('events');
var max_sleep=5000; // simulated maximum execution time in milliseconds for each process
var cnt=0;

function p1(jobs) {
    console.time('process-1');
    var slp=Math.floor(Math.random()*max_sleep)+1000;
    setTimeout( function() {
        cnt++;
        console.timeEnd('process-1');
        if(cnt>=2) {
            var m='from p1, cnt='+cnt;
            console.log(m);
            jobs.write(m);
        }
    }, slp );
}

function p2(jobs) {
    console.time('process-2');
    var slp=Math.floor(Math.random()*max_sleep)+1000;
    setTimeout( function() {
        cnt++;
        console.timeEnd('process-2');
        if(cnt>=2) {
            var m='from p2, cnt='+cnt;
            console.log(m);
            jobs.write(m);
        }
    }, slp );
}

function Jobs() {
    events.EventEmitter.call(this);
}

util.inherits(Jobs, events.EventEmitter);

Jobs.prototype.write=function(data) {
    this.emit('ready', data);
}

var jobs=new Jobs();

jobs.on('ready', function(data) {
    console.log('Received data: '+data);
    console.log('Job done!');
    console.timeEnd('all-processes');
});

console.time('all-processes');
p1(jobs);
p2(jobs);

Output examples:

1-
process-1: 1724ms
process-2: 3232ms
from p2, cnt=2
Received data: from p2, cnt=2
Job done!
all-processes: 3241ms

2-
process-2: 1377ms
process-1: 4803ms
from p1, cnt=2
Received data: from p1, cnt=2
Job done!
all-processes: 4805ms

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: