node.js http benchmark tool

用 node.js 自製一個類似 ab 的小巧工具~

需要 v0.6 以上支援的 cluster。

工作原理是建立一群 worker pool,同時去連個網站,work 工作完成以後再跑下一次,猜測應當是跟 ab 的作法差不多?!

目前預設參數是
url : www.yahoo.com.tw
times : 1000
numCPUs : 你電腦邏輯核心數(假設是 16)

就等同於跑

 $ ab -c 16 -n 1000 www.yahoo.com.tw/

耗費的時間是不太一樣~實作有差吧~

[mlwmlw@amlw ~]$ node nb.js
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests
Time per request:27.096ms
Time taken for tests:27.096s
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
var url = 'www.yahoo.com.tw';
var times = 1000;

if (cluster.isMaster) {
  // Fork workers.
  var workers = [];
  var counter = 0;
  var start;
  for (var i = 0; i < numCPUs; i++) {
    workers[i] = cluster.fork();
    workers[i].work = 0;

    workers[i].on("message", (function(num) {
    	return function(msg) {
	    	if(msg.cmd == 'done') {
	    		workers[num].work ++;
	    		counter++;

	    		//finish
	    		if(counter >= times) {
		    		var end = new Date();
		    		for(var j=0; j<numCPUs; j++) {
		    			//console.log('workers[' + j +']' + ' was finished ' + workers[j].work +' job');
		    			workers[j].send({'cmd': 'exit'});
		    			workers[j].emit('exit');

		    		}
		    		console.log('Finished ' + times + ' requests');
		    		console.log('Time per request:' + ((end-start)/times) + 'ms');

		    		console.log('Time taken for tests:' + ((end - start)/1000) + 's');

		    	}
		    	else {
		    		if(counter % 100 == 0) {
		    			console.log('Completed ' + counter + ' requests');
		    		}
		    		workers[num].send({'cmd': 'work'});
		    	}
	    	}
    	}
    })(i));

  }
  //ready
	start = new Date();
 	for (var k = 0; k < numCPUs; k++) {
 		workers[k].send({'cmd': 'work'});
 	}
  cluster.on('death', function(worker) {
    //console.log('worker ' + worker.pid + ' died');
  });
} else {
  // Worker processes have a http .
	var options = {
		host: url,
		port: 80
	};
	var alive = true;
	process.on('message', function(msg) {
		if(msg.cmd == 'exit') {
			alive = false;
		}
		else if(msg.cmd == 'work'){
			http.get(options, function(res) {
				res.on('data', function (chunk) {

		  	});
		  	res.on('end', function() {
		  		if(alive)
		  			process.send({'cmd' : 'done'});
		  	});
			}).on('error', function(e) {
				if(alive)
					process.send({'cmd' : 'failed'});
			});
		}
	});
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *