|
|
|
@ -12,10 +12,16 @@ var argv = require('optimist') |
|
|
|
default: 1, |
|
|
|
describe: 'Number of Concurrent Clients to Use' |
|
|
|
}) |
|
|
|
.options('r', { |
|
|
|
.options('n', { |
|
|
|
alias: 'requests', |
|
|
|
describe: 'Total Number Of Requests To Make' |
|
|
|
}) |
|
|
|
.options('r', { |
|
|
|
alias: 'random', |
|
|
|
describe: 'Whether Or Not To Randomize The Url Order', |
|
|
|
default: false, |
|
|
|
boolean: true |
|
|
|
}) |
|
|
|
.options('k', { |
|
|
|
alias: 'keepalive', |
|
|
|
describe: 'Whether Or Not To Enable Keep Alive Support', |
|
|
|
@ -61,7 +67,6 @@ if( argv.log ){ |
|
|
|
} |
|
|
|
|
|
|
|
var config = { |
|
|
|
random: false, |
|
|
|
urls: {}, |
|
|
|
}; |
|
|
|
var defaults = { |
|
|
|
@ -93,6 +98,10 @@ argv._.forEach(function(file){ |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
var results = []; |
|
|
|
var results_length = 0; |
|
|
|
var errors = []; |
|
|
|
var errors_length = 0; |
|
|
|
var urls = []; |
|
|
|
for( var key in config.urls ){ |
|
|
|
var url = config.urls[key]; |
|
|
|
@ -101,10 +110,7 @@ for( var key in config.urls ){ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if( typeof(config.random) !== 'boolean' ){ |
|
|
|
config.random = config.random.toLowerCase() === 'true'; |
|
|
|
} |
|
|
|
if( config.random ){ |
|
|
|
if( argv.random ){ |
|
|
|
console.log('Randomizing Url List'); |
|
|
|
var i = urls.length; |
|
|
|
if ( i == 0 ) return false; |
|
|
|
@ -121,11 +127,12 @@ if( !argv.requests ){ |
|
|
|
argv.requests = urls.length; |
|
|
|
} |
|
|
|
|
|
|
|
var results = []; |
|
|
|
var errors = []; |
|
|
|
|
|
|
|
var save_result = function(result){ |
|
|
|
results.push(result); |
|
|
|
var url = result.url; |
|
|
|
results[url] = (results[url])?results[url]:[]; |
|
|
|
results[url].push(result); |
|
|
|
results_length += 1; |
|
|
|
if( argv.log ){ |
|
|
|
var tmp = []; |
|
|
|
for( var i in result ){ |
|
|
|
@ -138,7 +145,15 @@ var save_result = function(result){ |
|
|
|
} |
|
|
|
fs.writeSync(argv.log, tmp.join() + '\r\n'); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
var save_error = function(error){ |
|
|
|
var url = error.url; |
|
|
|
errors[url] = (errors[url])?errors[url] : []; |
|
|
|
errors[url].push(error); |
|
|
|
errors_length += 1; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var run = function(options, done){ |
|
|
|
var start = new Date().getTime(); |
|
|
|
@ -168,37 +183,59 @@ var run = function(options, done){ |
|
|
|
console.log('Starting Up ' + argv.concurrency + ' Clients'); |
|
|
|
var queue = async.queue(run, argv.concurrency); |
|
|
|
|
|
|
|
var percentiles = [.7, .8, .85, .9, .94, .96, .99]; |
|
|
|
var percentiles = [.5, .6, .7, .8, .9, .95, .98, .99]; |
|
|
|
queue.drain = function(){ |
|
|
|
var end_time = new Date().getTime(); |
|
|
|
var elapsed = end_time - start_time; |
|
|
|
console.log('Finished'); |
|
|
|
console.log('Elapsed Time (sec): ' + (elapsed/1000)); |
|
|
|
console.log('Completed Requests: ' + results_length); |
|
|
|
console.log('Errors: ' + errors_length); |
|
|
|
var req_sec = results_length / (elapsed/1000); |
|
|
|
console.log('Requests per Second: ' + req_sec); |
|
|
|
|
|
|
|
if( argv.stats ){ |
|
|
|
console.log('Processing Results'); |
|
|
|
var tmp = results; |
|
|
|
results = {}; |
|
|
|
tmp.forEach( function(result){ |
|
|
|
var key = result.url; |
|
|
|
delete result.url; |
|
|
|
if( results[key] == undefined ){ |
|
|
|
results[key] = [] |
|
|
|
} |
|
|
|
results[key].push(result); |
|
|
|
}); |
|
|
|
|
|
|
|
for( var url in results ){ |
|
|
|
if( typeof(results[url]) === 'function' ){ |
|
|
|
continue; |
|
|
|
} |
|
|
|
console.log('Results For: ' + url); |
|
|
|
console.log('\tTotal Requests: ' + results[url].length); |
|
|
|
var ms_data = results[url].map( function(a){ return a.ms; } ); |
|
|
|
ms_data = ms_data.sort(); |
|
|
|
var ms_set = new gauss.Vector(ms_data); |
|
|
|
var ms_total = ms_set.sum(); |
|
|
|
console.log('\tMean Time (ms): ' + ms_set.mean()); |
|
|
|
console.log('\tMin Time (ms): ' + ms_set.min()); |
|
|
|
console.log('\tMax Time (ms): ' + ms_set.max()); |
|
|
|
console.log('\tTotal Time (ms): ' + ms_set.sum()); |
|
|
|
console.log('\tTotal Time (ms): ' + ms_total); |
|
|
|
percentiles.forEach( function(percent){ |
|
|
|
console.log('\t' + (percent*100) + 'th Percentile: ' + ms_set.percentile(percent)); |
|
|
|
console.log('\t' + (percent*100) + '% (ms): ' + ms_set.percentile(percent)); |
|
|
|
}); |
|
|
|
var status_data = results[url].map( function(a){ return a.status; } ); |
|
|
|
var status_set = new gauss.Vector(status_data); |
|
|
|
var status_dist = status_set.distribution(); |
|
|
|
console.log('\tStatus Code Distribution:'); |
|
|
|
for( var status in status_dist ){ |
|
|
|
console.log('\t\t' + status + '\t' + status_dist[status]); |
|
|
|
} |
|
|
|
} |
|
|
|
for( var url in errors){ |
|
|
|
if( typeof(errors[url]) == 'function' ){ |
|
|
|
continue; |
|
|
|
} |
|
|
|
console.log('Errors For: ' + url); |
|
|
|
console.log('\tErrors: ' + errors[url].length); |
|
|
|
var code_errors = errors[url].map( function(a){ return a.error.code; }); |
|
|
|
var code_set = new gauss.Vector(code_errors); |
|
|
|
var code_dist = code_set.distribution(); |
|
|
|
console.log('\tError Code Distribution:'); |
|
|
|
for( var code in code_dist ){ |
|
|
|
console.log('\t\t' + code + '\t' + code_dist[code]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if( argv.log ){ |
|
|
|
@ -209,6 +246,7 @@ queue.drain = function(){ |
|
|
|
|
|
|
|
console.log('Queuing Up ' + argv.requests + ' Requests'); |
|
|
|
var offset = 0; |
|
|
|
var start_time = new Date().getTime(); |
|
|
|
for( var i = 0; i < argv.requests; ++i ){ |
|
|
|
if( offset >= urls.length ){ |
|
|
|
offset = 0; |
|
|
|
|