diff --git a/Readme.md b/Readme.md index fcf5071..4f2a84d 100644 --- a/Readme.md +++ b/Readme.md @@ -18,14 +18,10 @@ npm install -g ## Configuration Tommygun uses ini files to specify what urls and settings to test. Each section corresponds to the url to test and -each property corresponds to specific settings for that given url. If the property occurs outside of a section then -tommygun those settings are used by tommygun. +each property corresponds to specific settings for that given url. ### Example ```ini -;this setting is used by tommygun globally -random = false - [localhost] port = 8000 num = 5 @@ -46,6 +42,17 @@ num = 2 ### Get Help ```bash tommygun --help +Usage: tommygun [config] [config]... + +Options: + -c, --concurrency Number of Concurrent Clients to Use [default: 1] + -n, --requests Total Number Of Requests To Make + -r, --random Whether Or Not To Randomize The Url Order [boolean] [default: false] + -k, --keepalive Whether Or Not To Enable Keep Alive Support [boolean] [default: false] + -l, --log Log File To Write All Request Data To [string] + -s, --stats Whether or Not Print Result Stats [boolean] [default: true] + -q, --quiet Whether Or Not To Silence stdout [boolean] [default: false] + -h, --help Show This Help Text [boolean] ``` ### Simple Usage diff --git a/lib/index.js b/lib/index.js index 27e92bf..099a49f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -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; diff --git a/package.json b/package.json index 4bb28e9..85cd78d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tommygun", - "version": "0.0.1", + "version": "0.0.2", "description": "HTTP Benchmarking Tool", "keywords": [ "http",