From ce27e73983e8aa3c3637a2be12269acdfd3543f9 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 14 Jun 2022 00:00:19 -0400 Subject: [PATCH 01/37] working commit --- lib/httpClient.js | 35 +++++++++++++++++++++-- sample/request-generator.js | 57 ++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index 1bd4d90..ae5aa01 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -106,15 +106,44 @@ class HttpClient { log.debug('Options: %j', this.options); } + randomExp(rps){ + let v = Number(rps); + v = -1/v; + let u = Math.random(); + u = Math.log(u); + let x = u*v; + return x; + } + /** * Start the HTTP client. */ start() { - if (!this.params.requestsPerSecond) { - return this.makeRequest(); + if (this.params.rpsInterval) { + const rps = this.params.requestsPerSecond; + if (this.params.agentKeepAlive) { + this.options.agent.maxSockets = 10 + rps; + } + // stop the old requesttimer + if (this.requestTimer !== undefined) { + this.requestTimer.stop(); + } + // Modification: Replace the fixed interval by exponential random interval + // which follows the poisson distribution + var cumulative_time = 0; + var temp = this.params.rpsInterval *1000; + while (cumulative_time< temp) { + var interval = 1000 * this.randomExp(rps); + cumulative_time += interval; + setTimeout(() => this.makeRequest(), cumulative_time); + } + log.info('total time:' + cumulative_time); } + else{ const interval = 1000 / this.params.requestsPerSecond; - this.requestTimer = new HighResolutionTimer(interval, () => this.makeRequest()); + // start new request timer + this.requestTimer = new HighResolutionTimer(interval, () => this.makeRequest()); + } } /** diff --git a/sample/request-generator.js b/sample/request-generator.js index 765fcdf..2992965 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -1,37 +1,36 @@ -'use strict'; - -/** - * Sample request generator usage. - * Contributed by jjohnsonvng: - * https://github.com/alexfernandez/loadtest/issues/86#issuecomment-211579639 - */ +// requires const loadtest = require('../lib/loadtest.js'); +const testserver = require('../lib/testserver.js'); +//const configuration = require('../sample/config.json'); + +const fs = require('fs'); + const options = { - url: 'http://yourHost', - concurrency: 5, - method: 'POST', - body:'', - requestsPerSecond:5, - maxSeconds:30, - requestGenerator: (params, options, client, callback) => { - const message = '{"hi": "ho"}'; - options.headers['Content-Length'] = message.length; - options.headers['Content-Type'] = 'application/json'; - options.body = 'YourPostData'; - options.path = 'YourURLPath'; - const request = client(options, callback); - request.write(message); - return request; - } + url: 'https://www.google.com/', + statusCallback: statusCallback, + requestsPerSecond: 5, + rpsInterval: 60 }; -loadtest.loadTest(options, (error, results) => { - if (error) { - return console.error('Got an error: %s', error); - } - console.log(results); - console.log('Tests run successfully'); + +function statusCallback(error, result, latency) { + console.log('----'); + console.log('Request elapsed milliseconds: ', result.requestElapsed); + let f = result.requestElapsed.toString()+ '\n'; + // fs.writeFile('test.txt', f, { flag: 'a+' }, err => {}); + console.log('Request index: ', result.requestIndex); +} + +loadtest.loadTest(options, function(error) { + if (error) { + return console.error('Got an error: %s', error); + } + console.log('Tests run successfully'); }); +// exports +exports.loadTest = loadtest.loadTest; +exports.startServer = testserver.startServer; + From 8e5815d9a7876e5de2fbe650724013116a7dd109 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 14 Jun 2022 00:19:57 -0400 Subject: [PATCH 02/37] implemented poisson arraival time given an rps interval --- sample/request-generator.ts | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 sample/request-generator.ts diff --git a/sample/request-generator.ts b/sample/request-generator.ts deleted file mode 100644 index d3e026c..0000000 --- a/sample/request-generator.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Sample request generator usage. - * Contributed by jjohnsonvng: - * https://github.com/alexfernandez/loadtest/issues/86#issuecomment-211579639 - */ - -import loadtest from "loadtest" - -const options: loadtest.LoadTestOptions = { - url: "http://yourHost", - concurrency: 5, - method: "POST", - body: "", - requestsPerSecond: 5, - maxSeconds: 30, - requestGenerator: (params, options, client, callback) => { - const message = '{"hi": "ho"}' - options.headers["Content-Length"] = message.length - options.headers["Content-Type"] = "application/json" - options.body = "YourPostData" - options.path = "YourURLPath" - const request = client(options, callback) - request.write(message) - return request - }, -} - -loadtest.loadTest(options, (error, results) => { - if (error) { - return console.error(`Got an error: ${error}`) - } - console.log("Tests run successfully", {results}) -}) From 051bf6f90986da422e806e59e0f7a438ba210c5b Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 28 Jun 2022 01:30:54 -0400 Subject: [PATCH 03/37] initial summary prints out --- lib/httpClient.js | 86 +++++++++++++++++++++++++++++++++---- sample/request-generator.js | 9 ++-- 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index ae5aa01..b70e309 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -16,9 +16,16 @@ const websocket = require('websocket'); const Log = require('log'); const {HighResolutionTimer} = require('./hrtimer.js'); const headers = require('./headers.js'); +const fs = require('fs'); // globals const log = new Log('info'); +var slowest; +var fastest; +var avg =0; +var mx; +const dta = []; + /** @@ -121,23 +128,36 @@ class HttpClient { start() { if (this.params.rpsInterval) { const rps = this.params.requestsPerSecond; - if (this.params.agentKeepAlive) { - this.options.agent.maxSockets = 10 + rps; - } - // stop the old requesttimer - if (this.requestTimer !== undefined) { - this.requestTimer.stop(); - } + if (this.params.agentKeepAlive) { + this.options.agent.maxSockets = 10 + rps; + } + // stop the old requesttimer + if (this.requestTimer !== undefined) { + this.requestTimer.stop(); + } // Modification: Replace the fixed interval by exponential random interval // which follows the poisson distribution var cumulative_time = 0; var temp = this.params.rpsInterval *1000; + var num_rquests =0; while (cumulative_time< temp) { + num_rquests++; var interval = 1000 * this.randomExp(rps); cumulative_time += interval; setTimeout(() => this.makeRequest(), cumulative_time); } - log.info('total time:' + cumulative_time); + mx = num_rquests; + let f = "Summary: " + '\n'; + fs.writeFile('summary.txt', f, { flag: 'w' }, err => {}); + f = "total time: "; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = cumulative_time/1000 + ' s\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = 'total requests: ' + num_rquests + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + var num = cumulative_time/1000; + f = 'throughput: ' + mx/num + ' req/s\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); } else{ const interval = 1000 / this.params.requestsPerSecond; @@ -243,15 +263,65 @@ class HttpClient { } const elapsed = this.operation.latency.end(id, errorCode); + avg+=elapsed; + + + + + if (elapsed < 0) { // not found or not running return; } const index = this.operation.latency.getRequestIndex(id); + dta[index]= elapsed; + + if (index==0){ + slowest = elapsed; + fastest = elapsed; + + } + else{ + if (elapsedslowest){ + slowest = elapsed; + } + if (index==mx-1){ + let f = 'average: ' + avg/mx/1000 + '\n' + 'fastest: ' + fastest/1000 + '\n'+ 'slowest: ' + slowest/1000 + '\n' ; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + + dta.sort(function(a, b){return a - b}); + + var p25 =( 0.25*(mx-1)).toFixed(); + f = '25%ile Latency: ' + dta[p25] + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + + var p50 =( 0.50*(mx-1)).toFixed(); + f = '50%ile Latency: ' + dta[p50] + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + + var p75 =( 0.75*(mx-1)).toFixed(); + f = '75%ile Latency: ' + dta[p75] + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + + var p99 =( 0.99*(mx-1)).toFixed(); + f = '99%ile Latency: ' + dta[p99] + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + + var p999 =( 0.999*(mx-1)).toFixed(); + f = '999%ile Latency: ' + dta[p999] + '\n'; + fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + } + } + if (result) { result.requestElapsed = elapsed; result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; + //result.startTime = this.operation.latency.getStartTime(id); } let callback; if (!this.params.requestsPerSecond) { diff --git a/sample/request-generator.js b/sample/request-generator.js index 2992965..6d92fce 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -2,7 +2,7 @@ // requires const loadtest = require('../lib/loadtest.js'); const testserver = require('../lib/testserver.js'); -//const configuration = require('../sample/config.json'); + const fs = require('fs'); @@ -10,8 +10,8 @@ const fs = require('fs'); const options = { url: 'https://www.google.com/', statusCallback: statusCallback, - requestsPerSecond: 5, - rpsInterval: 60 + requestsPerSecond: 100, + rpsInterval: 11 }; @@ -21,8 +21,11 @@ function statusCallback(error, result, latency) { let f = result.requestElapsed.toString()+ '\n'; // fs.writeFile('test.txt', f, { flag: 'a+' }, err => {}); console.log('Request index: ', result.requestIndex); + console.log('Code: ', result.statusCode); } + + loadtest.loadTest(options, function(error) { if (error) { return console.error('Got an error: %s', error); From 8d9bac5452c0e9cc64c63e1ce45067d200ec9f8c Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 5 Jul 2022 10:45:48 -0400 Subject: [PATCH 04/37] added timestamps, changed file type to csv, filenames include rps + interval --- lib/httpClient.js | 59 +++++++++++++++++++++---------------- sample/request-generator.js | 18 ++++++----- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index b70e309..79839b0 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -21,10 +21,12 @@ const fs = require('fs'); // globals const log = new Log('info'); var slowest; -var fastest; +var fastest; +var fileTitle2; var avg =0; var mx; const dta = []; +const timeStamps = []; @@ -138,26 +140,33 @@ class HttpClient { // Modification: Replace the fixed interval by exponential random interval // which follows the poisson distribution var cumulative_time = 0; - var temp = this.params.rpsInterval *1000; + var intr = this.params.rpsInterval *1000; var num_rquests =0; - while (cumulative_time< temp) { - num_rquests++; + while (cumulative_time< intr) { + + var interval = 1000 * this.randomExp(rps); cumulative_time += interval; - setTimeout(() => this.makeRequest(), cumulative_time); + timeStamps[num_rquests] = cumulative_time; + num_rquests++; + setTimeout(() => this.makeRequest(cumulative_time), cumulative_time); } + let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; + fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+intr/1000 + ".csv"; mx = num_rquests; let f = "Summary: " + '\n'; - fs.writeFile('summary.txt', f, { flag: 'w' }, err => {}); - f = "total time: "; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'w' }, err => {}); + f = 'Index, timestamp, latency, status code \n'; + fs.writeFile(fileTitle, f, { flag: 'w' }, err => {}); + f = 'total time: '; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); f = cumulative_time/1000 + ' s\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); f = 'total requests: ' + num_rquests + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); var num = cumulative_time/1000; f = 'throughput: ' + mx/num + ' req/s\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); } else{ const interval = 1000 / this.params.requestsPerSecond; @@ -178,7 +187,7 @@ class HttpClient { /** * Make a single request to the server. */ - makeRequest() { + makeRequest(timestamp) { if (!this.operation.running) { return; } @@ -186,7 +195,7 @@ class HttpClient { this.operation.requests += 1; const id = this.operation.latency.start(); - const requestFinished = this.getRequestFinisher(id); + const requestFinished = this.getRequestFinisher(id, timestamp); let lib = http; if (this.options.protocol == 'https:') { lib = https; @@ -245,7 +254,7 @@ class HttpClient { /** * Get a function that finishes one request and goes for the next. */ - getRequestFinisher(id) { + getRequestFinisher(id, timestamp) { return (error, result) => { let errorCode = null; if (error) { @@ -291,29 +300,29 @@ class HttpClient { } if (index==mx-1){ let f = 'average: ' + avg/mx/1000 + '\n' + 'fastest: ' + fastest/1000 + '\n'+ 'slowest: ' + slowest/1000 + '\n' ; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); dta.sort(function(a, b){return a - b}); var p25 =( 0.25*(mx-1)).toFixed(); - f = '25%ile Latency: ' + dta[p25] + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = '25%ile Latency: ' + dta[p25].toFixed(2) + '\n'; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); var p50 =( 0.50*(mx-1)).toFixed(); - f = '50%ile Latency: ' + dta[p50] + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = '50%ile Latency: ' + dta[p50].toFixed(2) + '\n'; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); var p75 =( 0.75*(mx-1)).toFixed(); - f = '75%ile Latency: ' + dta[p75] + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = '75%ile Latency: ' + dta[p75].toFixed(2) + '\n'; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); var p99 =( 0.99*(mx-1)).toFixed(); f = '99%ile Latency: ' + dta[p99] + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); var p999 =( 0.999*(mx-1)).toFixed(); - f = '999%ile Latency: ' + dta[p999] + '\n'; - fs.writeFile('summary.txt', f, { flag: 'a' }, err => {}); + f = '99.9%ile Latency: ' + dta[p999] + '\n'; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); } } @@ -321,7 +330,7 @@ class HttpClient { result.requestElapsed = elapsed; result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; - //result.startTime = this.operation.latency.getStartTime(id); + result.startTime = timeStamps[index]; } let callback; if (!this.params.requestsPerSecond) { diff --git a/sample/request-generator.js b/sample/request-generator.js index 6d92fce..f6c0274 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -5,22 +5,26 @@ const testserver = require('../lib/testserver.js'); const fs = require('fs'); - +rps = 10; +rpsInter= 10; +let fileTitle = "sample/log-rps-"+rps+"-iv-"+rpsInter+ ".csv"; const options = { - url: 'https://www.google.com/', + url: 'https://www.google.com', statusCallback: statusCallback, - requestsPerSecond: 100, - rpsInterval: 11 + requestsPerSecond: rps, + rpsInterval: rpsInter }; function statusCallback(error, result, latency) { console.log('----'); - console.log('Request elapsed milliseconds: ', result.requestElapsed); - let f = result.requestElapsed.toString()+ '\n'; - // fs.writeFile('test.txt', f, { flag: 'a+' }, err => {}); + console.log('Timestamp: ', result.startTime.toFixed(2)); console.log('Request index: ', result.requestIndex); + console.log('Request elapsed milliseconds: ', result.requestElapsed); + let n = result.requestElapsed.toFixed(); + let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + "\n"; + fs.writeFile(fileTitle, s, { flag: 'a+' }, err => {}); console.log('Code: ', result.statusCode); } From 500b43991c061493819e2b7638cb64dba32751b5 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 5 Jul 2022 10:46:34 -0400 Subject: [PATCH 05/37] Sarah's scripts --- scripts/cdf.py | 47 ++++++++++++++++++++++++++++++++++++++++++++ scripts/histogram.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 scripts/cdf.py create mode 100644 scripts/histogram.py diff --git a/scripts/cdf.py b/scripts/cdf.py new file mode 100644 index 0000000..82ebd4f --- /dev/null +++ b/scripts/cdf.py @@ -0,0 +1,47 @@ +import pandas as pd +import csv +import matplotlib.pyplot as plt +import numpy as np +import warnings + +#Put file you want to read in input folder + +#********************************************************************** +#List to store the data (ADD AS MUCH AS NECESSARY) +#********************************************************************** + +xlist = [] +ylist = [] + +#********************************************************************** +#File Read +#fname : put the name of the file you are reading +#********************************************************************** + +fname = "const_svc_cost_c20" + +#Change path +df = pd.read_csv(r'sample/output.txt'.format(fname), nrows=100) +print(df) + +#********************************************************************** +#df.iterrows returns series for each row it does not preserve data types across the rows +#iterate through the rows and take the data with it and append it to lists to use +#--------------------------------------------------------------------------------- +for index, row in df.iterrows(): + xlist.append(index) + #put header name of data you want in the hard brackets + ylist.append(row[' latency']) + + +#--------------------------------------------------------------------------------- +#********************************************************************** + +#-------------------------- +#CDF plot +#-------------------------- +sorted_data = np.sort(ylist) +yvals=np.arange(len(sorted_data))/float(len(sorted_data)-1) +plt.plot(sorted_data,yvals) +plt.show() +#********************************************************************** \ No newline at end of file diff --git a/scripts/histogram.py b/scripts/histogram.py new file mode 100644 index 0000000..eee8902 --- /dev/null +++ b/scripts/histogram.py @@ -0,0 +1,45 @@ +import pandas as pd +import csv +import matplotlib.pyplot as plt +import numpy as np + +#Put file you want to read in input folder +#********************************************************************** +#List to store the data (ADD AS MUCH AS NECESSARY) +#********************************************************************** + +xlist = [] +ylist = [] + +#********************************************************************** +#File Read +#fname : put the name of the file you are reading +#********************************************************************** + +fname = "const_svc_cost_c20" +#Change path +df = pd.read_csv(r'sample/output.txt'.format(fname), nrows=100) + +#********************************************************************** +#df.iterrows returns series for each row it does not preserve data types across the rows +#iterate through the rows and take the data with it and append it to lists +#--------------------------------------------------------------------------------- +for index, row in df.iterrows(): + # xlist.append(index) + #put header name of data you want in the hard brackets + xlist.append(float(row[' latency'])) + +#--------------------------------------------------------------------------------- +#********************************************************************** + +#-------------------------- +#Histogram plot +#-------------------------- +plt.figure(figsize=(14,7)) # Make it 14x7 inch +plt.style.use('seaborn-whitegrid') # nice and clean grid +plt.title('Response time', fontsize = 45) +plt.xlabel('X', fontsize = 25) +plt.ylabel('Y', fontsize = 25) +plt.hist(xlist, bins=20, facecolor = '#2ab0ff', edgecolor='#169acf', linewidth=0.5, alpha=0.7) +plt.show() +#-------------------------- \ No newline at end of file From 69a1c66536bd5359152c9b1bda9ab631565c5a9d Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Fri, 8 Jul 2022 00:11:18 -0400 Subject: [PATCH 06/37] fixed summary orders + added errors --- lib/httpClient.js | 74 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index 79839b0..75ce466 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -25,6 +25,7 @@ var fastest; var fileTitle2; var avg =0; var mx; +var errs = 0; const dta = []; const timeStamps = []; @@ -154,19 +155,18 @@ class HttpClient { let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+intr/1000 + ".csv"; mx = num_rquests; + + let m = 'Index, timestamp, latency, status code \n'; + fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); + let f = "Summary: " + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'w' }, err => {}); - f = 'Index, timestamp, latency, status code \n'; - fs.writeFile(fileTitle, f, { flag: 'w' }, err => {}); - f = 'total time: '; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - f = cumulative_time/1000 + ' s\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - f = 'total requests: ' + num_rquests + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + f = f + 'total time: '; + m = (cumulative_time/1000).toFixed(2) + ' s\n'; + f = f + m + 'total requests: ' + num_rquests + '\n'; + var num = cumulative_time/1000; - f = 'throughput: ' + mx/num + ' req/s\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + f = f + 'throughput: ' + (mx/num).toFixed(2) + ' req/s\n'; + fs.writeFile(fileTitle2, f, { flag: 'w' }, err => {}); } else{ const interval = 1000 / this.params.requestsPerSecond; @@ -299,30 +299,7 @@ class HttpClient { slowest = elapsed; } if (index==mx-1){ - let f = 'average: ' + avg/mx/1000 + '\n' + 'fastest: ' + fastest/1000 + '\n'+ 'slowest: ' + slowest/1000 + '\n' ; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - dta.sort(function(a, b){return a - b}); - - var p25 =( 0.25*(mx-1)).toFixed(); - f = '25%ile Latency: ' + dta[p25].toFixed(2) + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - var p50 =( 0.50*(mx-1)).toFixed(); - f = '50%ile Latency: ' + dta[p50].toFixed(2) + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - var p75 =( 0.75*(mx-1)).toFixed(); - f = '75%ile Latency: ' + dta[p75].toFixed(2) + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - var p99 =( 0.99*(mx-1)).toFixed(); - f = '99%ile Latency: ' + dta[p99] + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - var p999 =( 0.999*(mx-1)).toFixed(); - f = '99.9%ile Latency: ' + dta[p999] + '\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + this.percentile(); } } @@ -331,6 +308,9 @@ class HttpClient { result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; result.startTime = timeStamps[index]; + if (result.statusCode<200 || result.statusCode>299){ + errs++; + } } let callback; if (!this.params.requestsPerSecond) { @@ -340,6 +320,30 @@ class HttpClient { }; } + percentile(){ + let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/mx).toFixed(2) + ' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + + dta.sort(function(a, b){return a - b}); + + var p25 =( 0.25*(mx-1)).toFixed(); + f = '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; + + var p50 =( 0.50*(mx-1)).toFixed(); + f = f + '50%ile Latency: ' + dta[p50].toFixed(2) + ' ms\n'; + + var p75 =( 0.75*(mx-1)).toFixed(); + f = f + '75%ile Latency: ' + dta[p75].toFixed(2) + ' ms\n'; + + var p99 =( 0.99*(mx-1)).toFixed(); + f = f +'99%ile Latency: ' + dta[p99].toFixed(2) + ' ms\n'; + + + var p999 =( 0.999*(mx-1)).toFixed(); + f = f + '99.9%ile Latency: ' + dta[p999].toFixed(2) + ' ms\n'; + fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + } + /** * Get a function to connect the player. */ From 2a9cc70cb2ee2d3c1eeaa07e48a52e70bd46769f Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 11 Jul 2022 00:21:56 -0400 Subject: [PATCH 07/37] script fixes --- scripts/cdf.py | 10 +++++++--- scripts/histogram.py | 12 ++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/cdf.py b/scripts/cdf.py index 82ebd4f..73c1f24 100644 --- a/scripts/cdf.py +++ b/scripts/cdf.py @@ -21,8 +21,7 @@ fname = "const_svc_cost_c20" #Change path -df = pd.read_csv(r'sample/output.txt'.format(fname), nrows=100) -print(df) +df = pd.read_csv(r'sample/log-rps-10-iv-10.csv'.format(fname), nrows=100) #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows @@ -42,6 +41,11 @@ #-------------------------- sorted_data = np.sort(ylist) yvals=np.arange(len(sorted_data))/float(len(sorted_data)-1) -plt.plot(sorted_data,yvals) +plt.style.use('seaborn-whitegrid') # nice and clean grid +plt.title('Response time cdf') +plt.xlabel('response time (ms)') +plt.ylabel('cdf') +plt.ylim(0, 1) +plt.plot(sorted_data, yvals) plt.show() #********************************************************************** \ No newline at end of file diff --git a/scripts/histogram.py b/scripts/histogram.py index eee8902..ad8fa56 100644 --- a/scripts/histogram.py +++ b/scripts/histogram.py @@ -18,7 +18,7 @@ fname = "const_svc_cost_c20" #Change path -df = pd.read_csv(r'sample/output.txt'.format(fname), nrows=100) +df = pd.read_csv(r'sample/log-rps-10-iv-10.csv'.format(fname), nrows=100) #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows @@ -35,11 +35,11 @@ #-------------------------- #Histogram plot #-------------------------- -plt.figure(figsize=(14,7)) # Make it 14x7 inch +plt.figure(figsize=(10,5)) # Make it 14x7 inch plt.style.use('seaborn-whitegrid') # nice and clean grid -plt.title('Response time', fontsize = 45) -plt.xlabel('X', fontsize = 25) -plt.ylabel('Y', fontsize = 25) -plt.hist(xlist, bins=20, facecolor = '#2ab0ff', edgecolor='#169acf', linewidth=0.5, alpha=0.7) +plt.title('Response time', fontsize = 40) +plt.xlabel('response time (ms)', fontsize = 20) +plt.ylabel('number of occurences', fontsize = 20) +plt.hist(xlist, facecolor = '#2ab0ff', edgecolor='#169acf', linewidth=0.5, alpha=0.7) plt.show() #-------------------------- \ No newline at end of file From dc0578a9428736eac4662dc27d73fcbbb90a5c26 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 11 Jul 2022 00:24:10 -0400 Subject: [PATCH 08/37] intitial automation can run multiple tests given a list of rps rates and a flask file name --- automation/function.py | 9 +++++++++ automation/run.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 automation/function.py create mode 100644 automation/run.py diff --git a/automation/function.py b/automation/function.py new file mode 100644 index 0000000..34292c3 --- /dev/null +++ b/automation/function.py @@ -0,0 +1,9 @@ +import os +from flask import Flask +fibapp = Flask(__name__) +@fibapp.route('/') +def index(): + return "Hello World!" + +if __name__ == '__main__': + fibapp.run() \ No newline at end of file diff --git a/automation/run.py b/automation/run.py new file mode 100644 index 0000000..fd1ca54 --- /dev/null +++ b/automation/run.py @@ -0,0 +1,33 @@ +import os, json +from tracemalloc import start +#from plumbum import RETCODE, SshMachine, cli, local, BG, FG +from Naked.toolshed.shell import execute_js + + + +def generateLoad(req, duration): + command = "sample/request-generator.js --rps=" + str(req) + " --interval=" + str(duration) + execute_js(command) #run the script with the arguments + +def start_function(): + ## use this to start the flask or sledge + exec(open("automation/function.py").read()) + return + +def run_test(rps, duration): + out = generateLoad(rps, duration) + return out + + +def main(): + TEST_LIST = [0, 5, 10, 50, 100] + duration = 10 + #start_function() + for test in TEST_LIST: + ld_out = run_test(test, duration) + + + + +if __name__ == "__main__": + main() \ No newline at end of file From a7288b7cf0aeaf993238caf723272d60e5f4c493 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 11 Jul 2022 00:25:24 -0400 Subject: [PATCH 09/37] fixed bug of script not ending moved most of summary to request generator instead of httpclient --- lib/httpClient.js | 39 +++++++------------- sample/request-generator.js | 72 +++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 29 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index 75ce466..358e3fa 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -150,10 +150,10 @@ class HttpClient { cumulative_time += interval; timeStamps[num_rquests] = cumulative_time; num_rquests++; - setTimeout(() => this.makeRequest(cumulative_time), cumulative_time); + setTimeout(() => this.makeRequest(), cumulative_time); } let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; - fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+intr/1000 + ".csv"; + fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+intr/1000 + ".txt"; mx = num_rquests; let m = 'Index, timestamp, latency, status code \n'; @@ -187,7 +187,7 @@ class HttpClient { /** * Make a single request to the server. */ - makeRequest(timestamp) { + makeRequest() { if (!this.operation.running) { return; } @@ -195,7 +195,7 @@ class HttpClient { this.operation.requests += 1; const id = this.operation.latency.start(); - const requestFinished = this.getRequestFinisher(id, timestamp); + const requestFinished = this.getRequestFinisher(id); let lib = http; if (this.options.protocol == 'https:') { lib = https; @@ -272,7 +272,7 @@ class HttpClient { } const elapsed = this.operation.latency.end(id, errorCode); - avg+=elapsed; + @@ -285,23 +285,7 @@ class HttpClient { const index = this.operation.latency.getRequestIndex(id); dta[index]= elapsed; - if (index==0){ - slowest = elapsed; - fastest = elapsed; - - } - else{ - if (elapsedslowest){ - slowest = elapsed; - } - if (index==mx-1){ - this.percentile(); - } - } + if (result) { result.requestElapsed = elapsed; @@ -312,6 +296,8 @@ class HttpClient { errs++; } } + + let callback; if (!this.params.requestsPerSecond) { callback = this.makeRequest.bind(this); @@ -322,12 +308,12 @@ class HttpClient { percentile(){ let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/mx).toFixed(2) + ' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + //fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); dta.sort(function(a, b){return a - b}); var p25 =( 0.25*(mx-1)).toFixed(); - f = '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; + f = f + '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; var p50 =( 0.50*(mx-1)).toFixed(); f = f + '50%ile Latency: ' + dta[p50].toFixed(2) + ' ms\n'; @@ -336,12 +322,13 @@ class HttpClient { f = f + '75%ile Latency: ' + dta[p75].toFixed(2) + ' ms\n'; var p99 =( 0.99*(mx-1)).toFixed(); - f = f +'99%ile Latency: ' + dta[p99].toFixed(2) + ' ms\n'; + f = f +'99%ile Latency: ' + dta[p99] + ' ms\n'; var p999 =( 0.999*(mx-1)).toFixed(); - f = f + '99.9%ile Latency: ' + dta[p999].toFixed(2) + ' ms\n'; + f = f + '99.9%ile Latency: ' + dta[p999] + ' ms\n'; fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + return; } /** diff --git a/sample/request-generator.js b/sample/request-generator.js index f6c0274..33ef1a5 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -2,15 +2,25 @@ // requires const loadtest = require('../lib/loadtest.js'); const testserver = require('../lib/testserver.js'); +const args = require('minimist')(process.argv.slice(2)); const fs = require('fs'); -rps = 10; -rpsInter= 10; +rps = args.rps; +rpsInter= args.interval; +const dta = []; +var errs= 0; +var slowest; +var fastest; +var mx; +var avg; + + let fileTitle = "sample/log-rps-"+rps+"-iv-"+rpsInter+ ".csv"; +let fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+rpsInter + ".txt"; const options = { - url: 'https://www.google.com', + url: 'http://127.0.0.1:5000', statusCallback: statusCallback, requestsPerSecond: rps, rpsInterval: rpsInter @@ -22,18 +32,74 @@ function statusCallback(error, result, latency) { console.log('Timestamp: ', result.startTime.toFixed(2)); console.log('Request index: ', result.requestIndex); console.log('Request elapsed milliseconds: ', result.requestElapsed); + dta[result.requestIndex]= result.requestElapsed; let n = result.requestElapsed.toFixed(); let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + "\n"; fs.writeFile(fileTitle, s, { flag: 'a+' }, err => {}); console.log('Code: ', result.statusCode); + + avg+=result.requestElapsed; + if (result.requestIndex==0){ + slowest =result.requestElapsed; + fastest = result.requestElapsed; + + } + else{ + if (result.requestElapsedslowest){ + slowest = result.requestElapsed; + } + } + + + if ( result.statusCode>299){ + errs++; + } + + if ( result.startTime>rpsInter*1000){ + mx = result.requestIndex +1; + percentile(); + process.exit(0); + } } +function percentile(){ + let f = 'errors: ' + errs + '\n' + 'average: ' + avg/mx +' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; + //fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + + dta.sort(function(a, b){return a - b}); + + var p25 =( 0.25*(mx-1)).toFixed(); + f = f + '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; + + var p50 =( 0.50*(mx-1)).toFixed(); + f = f + '50%ile Latency: ' + dta[p50].toFixed(2) + ' ms\n'; + + var p75 =( 0.75*(mx-1)).toFixed(); + f = f + '75%ile Latency: ' + dta[p75].toFixed(2) + ' ms\n'; + + var p99 =( 0.99*(mx-1)).toFixed(); + f = f +'99%ile Latency: ' + dta[p99] + ' ms\n'; + + + var p999 =( 0.999*(mx-1)).toFixed(); + f = f + '99.9%ile Latency: ' + dta[p999] + ' ms\n'; + + fs.writeFileSync(fileTitle2, f, { flag: 'a' }, err => {}); +} + + loadtest.loadTest(options, function(error) { if (error) { return console.error('Got an error: %s', error); + } + console.log('Tests run successfully'); }); From 1e080ea33bd63a5c120d7bde044f85655e9593e1 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 11 Jul 2022 14:55:20 -0400 Subject: [PATCH 10/37] summary average bug fix --- automation/run.py | 2 +- sample/request-generator.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/automation/run.py b/automation/run.py index fd1ca54..c62befc 100644 --- a/automation/run.py +++ b/automation/run.py @@ -20,7 +20,7 @@ def run_test(rps, duration): def main(): - TEST_LIST = [0, 5, 10, 50, 100] + TEST_LIST = [1, 5, 10, 50, 100] duration = 10 #start_function() for test in TEST_LIST: diff --git a/sample/request-generator.js b/sample/request-generator.js index 33ef1a5..5194ae2 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -13,7 +13,7 @@ var errs= 0; var slowest; var fastest; var mx; -var avg; +var avg =0; let fileTitle = "sample/log-rps-"+rps+"-iv-"+rpsInter+ ".csv"; @@ -38,7 +38,7 @@ function statusCallback(error, result, latency) { fs.writeFile(fileTitle, s, { flag: 'a+' }, err => {}); console.log('Code: ', result.statusCode); - avg+=result.requestElapsed; + avg+=parseFloat(result.requestElapsed); if (result.requestIndex==0){ slowest =result.requestElapsed; fastest = result.requestElapsed; @@ -67,7 +67,7 @@ function statusCallback(error, result, latency) { } function percentile(){ - let f = 'errors: ' + errs + '\n' + 'average: ' + avg/mx +' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; + let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/mx).toFixed(2) +' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; //fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); dta.sort(function(a, b){return a - b}); From c1449c1cd15e28438dce7c63ecc7281a00218533 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 11 Jul 2022 18:00:09 -0400 Subject: [PATCH 11/37] used forked process to start flask --- automation/function.py | 0 automation/run.py | 10 +++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) mode change 100644 => 100755 automation/function.py diff --git a/automation/function.py b/automation/function.py old mode 100644 new mode 100755 diff --git a/automation/run.py b/automation/run.py index c62befc..994832b 100644 --- a/automation/run.py +++ b/automation/run.py @@ -1,6 +1,6 @@ import os, json +import subprocess from tracemalloc import start -#from plumbum import RETCODE, SshMachine, cli, local, BG, FG from Naked.toolshed.shell import execute_js @@ -11,7 +11,11 @@ def generateLoad(req, duration): def start_function(): ## use this to start the flask or sledge - exec(open("automation/function.py").read()) + n = os.fork() + if n > 0: + print("hi") + else: + exec(open("automation/function.py").read()) return def run_test(rps, duration): @@ -22,7 +26,7 @@ def run_test(rps, duration): def main(): TEST_LIST = [1, 5, 10, 50, 100] duration = 10 - #start_function() + start_function() for test in TEST_LIST: ld_out = run_test(test, duration) From 08cf5d50e02b0df2698787e60786efc393e1b7e3 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 12 Jul 2022 00:19:12 -0400 Subject: [PATCH 12/37] amanda's script + 99ile graphing script --- scripts/99ile.py | 15 +++++++++++++++ scripts/linegraph.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 scripts/99ile.py create mode 100644 scripts/linegraph.py diff --git a/scripts/99ile.py b/scripts/99ile.py new file mode 100644 index 0000000..a34ad78 --- /dev/null +++ b/scripts/99ile.py @@ -0,0 +1,15 @@ +import csv +import matplotlib.pyplot as plt +import pandas as pd + +df = pd.read_csv("sample/rps-99ile.csv") +print(df) +data = [] +num = [] +for index, row in df.iterrows(): + num.append(row['rps']) + #put header name of data you want in the hard brackets + data.append(row[' 99ile']) + +plt.plot(num, data) +plt.show() \ No newline at end of file diff --git a/scripts/linegraph.py b/scripts/linegraph.py new file mode 100644 index 0000000..205c337 --- /dev/null +++ b/scripts/linegraph.py @@ -0,0 +1,44 @@ +import csv +import matplotlib.pyplot as plt +import pandas as pd + +plt.figure() + +file_names = ['sample/log-rps-100-iv-10.csv','sample/log-rps-50-iv-10.csv','sample/log-rps-10-iv-10.csv'] +subplotnum = (len(file_names)*100)+11 #should be 311 for 3 files, 211 for 2 files, etc + + +def create_subplot (data): + with open (data) as csv_file: + next(csv_file) + csv_reader = csv.reader(csv_file, delimiter=',') + i = 0 + data = [] + num = [] + for row in csv_reader: + data.append((float)(row[0])) + num.append(i) + i+=1 + plt.subplot(subplotnum) + plt.plot(num, data) + +def read_file(file): + df = pd.read_csv(file) + print(df) + data = [] + num = [] + for index, row in df.iterrows(): + num.append(index) + #put header name of data you want in the hard brackets + data.append(row[' latency']) + plt.subplot(subplotnum) + plt.plot(num, data) + + +for file in file_names: + #create_subplot(file) + read_file(file) + subplotnum += 1 + +plt.show() +#plt.savefig('line_plot.pdf', format='pdf') \ No newline at end of file From bc06033386eadf0d48e4df9edc1538965e9d8c8a Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Thu, 14 Jul 2022 11:17:17 -0400 Subject: [PATCH 13/37] scripts as pictures --- scripts/99ile.py | 8 +++++++- scripts/cdf.py | 10 +++++----- scripts/histogram.py | 14 +++++++------- scripts/linegraph.py | 8 ++++---- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/scripts/99ile.py b/scripts/99ile.py index a34ad78..3903969 100644 --- a/scripts/99ile.py +++ b/scripts/99ile.py @@ -6,10 +6,16 @@ print(df) data = [] num = [] +f, ax = plt.subplots(1) for index, row in df.iterrows(): num.append(row['rps']) #put header name of data you want in the hard brackets data.append(row[' 99ile']) -plt.plot(num, data) +plt.title('99ile latency vs Rps', fontsize = 18) +plt.xlabel('rps rate', fontsize = 12) +plt.ylabel('99ile latency', fontsize = 12) +ax.plot(num, data) +ax.set_xlim(left=0) +plt.savefig('99ile_plot.png') plt.show() \ No newline at end of file diff --git a/scripts/cdf.py b/scripts/cdf.py index 73c1f24..8e4cb8e 100644 --- a/scripts/cdf.py +++ b/scripts/cdf.py @@ -18,10 +18,9 @@ #fname : put the name of the file you are reading #********************************************************************** -fname = "const_svc_cost_c20" #Change path -df = pd.read_csv(r'sample/log-rps-10-iv-10.csv'.format(fname), nrows=100) +df = pd.read_csv('sample/log-rps-100-iv-10.csv') #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows @@ -42,10 +41,11 @@ sorted_data = np.sort(ylist) yvals=np.arange(len(sorted_data))/float(len(sorted_data)-1) plt.style.use('seaborn-whitegrid') # nice and clean grid -plt.title('Response time cdf') -plt.xlabel('response time (ms)') -plt.ylabel('cdf') +plt.title('Response time cdf', fontsize = 21) +plt.xlabel('response time (ms)', fontsize = 15) +plt.ylabel('cdf', fontsize = 15) plt.ylim(0, 1) plt.plot(sorted_data, yvals) +plt.savefig('cdf_plot.png') plt.show() #********************************************************************** \ No newline at end of file diff --git a/scripts/histogram.py b/scripts/histogram.py index ad8fa56..9701b2b 100644 --- a/scripts/histogram.py +++ b/scripts/histogram.py @@ -16,9 +16,8 @@ #fname : put the name of the file you are reading #********************************************************************** -fname = "const_svc_cost_c20" #Change path -df = pd.read_csv(r'sample/log-rps-10-iv-10.csv'.format(fname), nrows=100) +df = pd.read_csv('sample/log-rps-100-iv-10.csv') #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows @@ -35,11 +34,12 @@ #-------------------------- #Histogram plot #-------------------------- -plt.figure(figsize=(10,5)) # Make it 14x7 inch +#plt.figure(figsize=(10,5)) # Make it 14x7 inch plt.style.use('seaborn-whitegrid') # nice and clean grid -plt.title('Response time', fontsize = 40) -plt.xlabel('response time (ms)', fontsize = 20) -plt.ylabel('number of occurences', fontsize = 20) -plt.hist(xlist, facecolor = '#2ab0ff', edgecolor='#169acf', linewidth=0.5, alpha=0.7) +plt.title('Response time', fontsize = 21) +plt.xlabel('response time (ms)', fontsize = 15) +plt.ylabel('number of occurences', fontsize = 15) +plt.hist(xlist, linewidth=0.5, alpha=0.7) +plt.savefig('hist_plot.png') plt.show() #-------------------------- \ No newline at end of file diff --git a/scripts/linegraph.py b/scripts/linegraph.py index 205c337..83c9ca4 100644 --- a/scripts/linegraph.py +++ b/scripts/linegraph.py @@ -4,7 +4,7 @@ plt.figure() -file_names = ['sample/log-rps-100-iv-10.csv','sample/log-rps-50-iv-10.csv','sample/log-rps-10-iv-10.csv'] +file_names = ['sample/log-rps-1000-iv-10.csv','sample/log-rps-100-iv-10.csv','sample/log-rps-10-iv-10.csv'] subplotnum = (len(file_names)*100)+11 #should be 311 for 3 files, 211 for 2 files, etc @@ -24,21 +24,21 @@ def create_subplot (data): def read_file(file): df = pd.read_csv(file) - print(df) data = [] num = [] for index, row in df.iterrows(): num.append(index) #put header name of data you want in the hard brackets data.append(row[' latency']) - plt.subplot(subplotnum) + ax = plt.subplot(subplotnum) plt.plot(num, data) +plt.suptitle("Latency over time(ms)", fontsize=16) for file in file_names: #create_subplot(file) read_file(file) subplotnum += 1 - +plt.savefig('line_plot.png') plt.show() #plt.savefig('line_plot.pdf', format='pdf') \ No newline at end of file From 5279745c95ea0136fd740059d294e0ecfdd03877 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 25 Jul 2022 22:32:56 -0400 Subject: [PATCH 14/37] clean up for code review --- automation/function.py | 7 +++++ automation/run.py | 20 ++----------- lib/httpClient.js | 60 +++++-------------------------------- sample/request-generator.js | 41 +++++++++++++++---------- scripts/linegraph.py | 18 +---------- 5 files changed, 44 insertions(+), 102 deletions(-) diff --git a/automation/function.py b/automation/function.py index 34292c3..d03f88b 100755 --- a/automation/function.py +++ b/automation/function.py @@ -1,9 +1,16 @@ import os +import time from flask import Flask fibapp = Flask(__name__) @fibapp.route('/') def index(): + # temp() return "Hello World!" +def temp(): + time.sleep(0.1) + print("waited") + return + if __name__ == '__main__': fibapp.run() \ No newline at end of file diff --git a/automation/run.py b/automation/run.py index 994832b..deb918c 100644 --- a/automation/run.py +++ b/automation/run.py @@ -9,26 +9,12 @@ def generateLoad(req, duration): command = "sample/request-generator.js --rps=" + str(req) + " --interval=" + str(duration) execute_js(command) #run the script with the arguments -def start_function(): - ## use this to start the flask or sledge - n = os.fork() - if n > 0: - print("hi") - else: - exec(open("automation/function.py").read()) - return - -def run_test(rps, duration): - out = generateLoad(rps, duration) - return out - - def main(): - TEST_LIST = [1, 5, 10, 50, 100] + TEST_LIST = [1, 5, 10, 50, 100, 500, 1000] duration = 10 - start_function() + # start_function() for test in TEST_LIST: - ld_out = run_test(test, duration) + generateLoad(test, duration) diff --git a/lib/httpClient.js b/lib/httpClient.js index 358e3fa..b353465 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -20,14 +20,7 @@ const fs = require('fs'); // globals const log = new Log('info'); -var slowest; -var fastest; -var fileTitle2; -var avg =0; -var mx; -var errs = 0; -const dta = []; -const timeStamps = []; +const timeStamps = []; // added for gwloadtest timestamps @@ -144,29 +137,17 @@ class HttpClient { var intr = this.params.rpsInterval *1000; var num_rquests =0; while (cumulative_time< intr) { - - var interval = 1000 * this.randomExp(rps); cumulative_time += interval; timeStamps[num_rquests] = cumulative_time; num_rquests++; - setTimeout(() => this.makeRequest(), cumulative_time); + setTimeout(() => this.makeRequest(), cumulative_time); // sets a timer for all the requests } + // starts the log file for each request let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; - fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+intr/1000 + ".txt"; - mx = num_rquests; - let m = 'Index, timestamp, latency, status code \n'; - fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); - - let f = "Summary: " + '\n'; - f = f + 'total time: '; - m = (cumulative_time/1000).toFixed(2) + ' s\n'; - f = f + m + 'total requests: ' + num_rquests + '\n'; + fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); - var num = cumulative_time/1000; - f = f + 'throughput: ' + (mx/num).toFixed(2) + ' req/s\n'; - fs.writeFile(fileTitle2, f, { flag: 'w' }, err => {}); } else{ const interval = 1000 / this.params.requestsPerSecond; @@ -283,7 +264,7 @@ class HttpClient { return; } const index = this.operation.latency.getRequestIndex(id); - dta[index]= elapsed; + @@ -291,10 +272,8 @@ class HttpClient { result.requestElapsed = elapsed; result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; - result.startTime = timeStamps[index]; - if (result.statusCode<200 || result.statusCode>299){ - errs++; - } + result.startTime = timeStamps[index]; // stores the timestamps pf teh request added for gwloadtest + //console.log(result.body) } @@ -306,31 +285,6 @@ class HttpClient { }; } - percentile(){ - let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/mx).toFixed(2) + ' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; - //fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - - dta.sort(function(a, b){return a - b}); - - var p25 =( 0.25*(mx-1)).toFixed(); - f = f + '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; - - var p50 =( 0.50*(mx-1)).toFixed(); - f = f + '50%ile Latency: ' + dta[p50].toFixed(2) + ' ms\n'; - - var p75 =( 0.75*(mx-1)).toFixed(); - f = f + '75%ile Latency: ' + dta[p75].toFixed(2) + ' ms\n'; - - var p99 =( 0.99*(mx-1)).toFixed(); - f = f +'99%ile Latency: ' + dta[p99] + ' ms\n'; - - - var p999 =( 0.999*(mx-1)).toFixed(); - f = f + '99.9%ile Latency: ' + dta[p999] + ' ms\n'; - fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); - return; - } - /** * Get a function to connect the player. */ diff --git a/sample/request-generator.js b/sample/request-generator.js index 5194ae2..80d05dd 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -10,9 +10,9 @@ rps = args.rps; rpsInter= args.interval; const dta = []; var errs= 0; -var slowest; +var slowest; var fastest; -var mx; +var max; var avg =0; @@ -21,24 +21,26 @@ let fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+rpsInter + ".txt"; const options = { url: 'http://127.0.0.1:5000', - statusCallback: statusCallback, + statusCallback: statusCallback, requestsPerSecond: rps, rpsInterval: rpsInter }; - +//the function called after every request is finished function statusCallback(error, result, latency) { console.log('----'); console.log('Timestamp: ', result.startTime.toFixed(2)); console.log('Request index: ', result.requestIndex); console.log('Request elapsed milliseconds: ', result.requestElapsed); - dta[result.requestIndex]= result.requestElapsed; + console.log('Code: ', result.statusCode); + let n = result.requestElapsed.toFixed(); let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + "\n"; fs.writeFile(fileTitle, s, { flag: 'a+' }, err => {}); - console.log('Code: ', result.statusCode); + dta[result.requestIndex]= result.requestElapsed; // store elpased for percentile calculation + + avg+=parseFloat(result.requestElapsed); // add to sum - avg+=parseFloat(result.requestElapsed); if (result.requestIndex==0){ slowest =result.requestElapsed; fastest = result.requestElapsed; @@ -60,32 +62,41 @@ function statusCallback(error, result, latency) { } if ( result.startTime>rpsInter*1000){ - mx = result.requestIndex +1; + max = result.requestIndex +1; + // print summary after last request + let f = "Summary: " + '\n'; + f = f + 'total time: '; + m = (result.startTime/1000).toFixed(2) + ' s\n'; + f = f + m + 'total requests: ' + max + '\n'; + + var num = result.startTime/1000; + f = f + 'throughput: ' + (max/num).toFixed(2) + ' req/s\n'; + fs.writeFileSync(fileTitle2, f, { flag: 'w' }, err => {}); + percentile(); process.exit(0); } } function percentile(){ - let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/mx).toFixed(2) +' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; - //fs.writeFile(fileTitle2, f, { flag: 'a' }, err => {}); + let f = 'errors: ' + errs + '\n' + 'average: ' + (avg/max).toFixed(2) +' ms\n' + 'fastest: ' + fastest.toFixed(2) + ' ms\n'+ 'slowest: ' + slowest.toFixed(2) + ' ms\n' ; dta.sort(function(a, b){return a - b}); - var p25 =( 0.25*(mx-1)).toFixed(); + var p25 =( 0.25*(max-1)).toFixed(); f = f + '25%ile Latency: ' + dta[p25].toFixed(2) + ' ms\n'; - var p50 =( 0.50*(mx-1)).toFixed(); + var p50 =( 0.50*(max-1)).toFixed(); f = f + '50%ile Latency: ' + dta[p50].toFixed(2) + ' ms\n'; - var p75 =( 0.75*(mx-1)).toFixed(); + var p75 =( 0.75*(max-1)).toFixed(); f = f + '75%ile Latency: ' + dta[p75].toFixed(2) + ' ms\n'; - var p99 =( 0.99*(mx-1)).toFixed(); + var p99 =( 0.99*(max-1)).toFixed(); f = f +'99%ile Latency: ' + dta[p99] + ' ms\n'; - var p999 =( 0.999*(mx-1)).toFixed(); + var p999 =( 0.999*(max-1)).toFixed(); f = f + '99.9%ile Latency: ' + dta[p999] + ' ms\n'; fs.writeFileSync(fileTitle2, f, { flag: 'a' }, err => {}); diff --git a/scripts/linegraph.py b/scripts/linegraph.py index 83c9ca4..84adb85 100644 --- a/scripts/linegraph.py +++ b/scripts/linegraph.py @@ -7,21 +7,6 @@ file_names = ['sample/log-rps-1000-iv-10.csv','sample/log-rps-100-iv-10.csv','sample/log-rps-10-iv-10.csv'] subplotnum = (len(file_names)*100)+11 #should be 311 for 3 files, 211 for 2 files, etc - -def create_subplot (data): - with open (data) as csv_file: - next(csv_file) - csv_reader = csv.reader(csv_file, delimiter=',') - i = 0 - data = [] - num = [] - for row in csv_reader: - data.append((float)(row[0])) - num.append(i) - i+=1 - plt.subplot(subplotnum) - plt.plot(num, data) - def read_file(file): df = pd.read_csv(file) data = [] @@ -36,9 +21,8 @@ def read_file(file): plt.suptitle("Latency over time(ms)", fontsize=16) for file in file_names: - #create_subplot(file) + read_file(file) subplotnum += 1 plt.savefig('line_plot.png') plt.show() -#plt.savefig('line_plot.pdf', format='pdf') \ No newline at end of file From fd889c1b3f297281c93c10b949d431e1eb0dc05a Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 1 Aug 2022 23:58:50 -0400 Subject: [PATCH 15/37] policy 1: weighted urls working --- lib/httpClient.js | 67 +++++++++++++++++++++++++++++++++++-- sample/request-generator.js | 3 +- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index b353465..65ed82f 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -21,7 +21,8 @@ const fs = require('fs'); // globals const log = new Log('info'); const timeStamps = []; // added for gwloadtest timestamps - +var url_list; //added for gwloadtest client behaviour +var total; //added for gwloadtest client behaviour /** @@ -143,6 +144,7 @@ class HttpClient { num_rquests++; setTimeout(() => this.makeRequest(), cumulative_time); // sets a timer for all the requests } + total = num_rquests; // starts the log file for each request let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; let m = 'Index, timestamp, latency, status code \n'; @@ -154,8 +156,46 @@ class HttpClient { // start new request timer this.requestTimer = new HighResolutionTimer(interval, () => this.makeRequest()); } + //gwloadtest modification: read url list to make requested according to weights + if (this.params.url_list){ + try { + const data = fs.readFileSync(this.params.url_list, 'utf8'); + var arr = this.fileToArray(data, ', ') + url_list = arr; + for (var i=0; i0){ + url_list[num].weight--; + temp=url_list[num].url; + console.log(temp); + break; + } + } + + console.log(num); + //hint use the max num of requests multiply weights by total + + } + else { + temp = this.options; + } + + request = lib.request(temp, this.getConnect(id, requestFinished, this.params.contentInspector)); } if (this.params.timeout) { const timeout = parseInt(this.params.timeout); diff --git a/sample/request-generator.js b/sample/request-generator.js index 80d05dd..e2dbb8f 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -23,7 +23,8 @@ const options = { url: 'http://127.0.0.1:5000', statusCallback: statusCallback, requestsPerSecond: rps, - rpsInterval: rpsInter + rpsInterval: rpsInter, + url_list: 'sample/url_list.txt' }; //the function called after every request is finished From 403353a02f08edeac9f39f223a44d8a57cfbe200 Mon Sep 17 00:00:00 2001 From: ascoville22 <108968358+ascoville22@users.noreply.github.com> Date: Fri, 12 Aug 2022 19:19:15 -0700 Subject: [PATCH 16/37] Update linegraph.py --- scripts/linegraph.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/linegraph.py b/scripts/linegraph.py index 84adb85..0279f37 100644 --- a/scripts/linegraph.py +++ b/scripts/linegraph.py @@ -1,28 +1,38 @@ import csv import matplotlib.pyplot as plt -import pandas as pd +import os plt.figure() -file_names = ['sample/log-rps-1000-iv-10.csv','sample/log-rps-100-iv-10.csv','sample/log-rps-10-iv-10.csv'] +all_files = os.listdir(os.getcwd()) +file_names = list(filter(lambda f: f.endswith('.csv'), all_files)) subplotnum = (len(file_names)*100)+11 #should be 311 for 3 files, 211 for 2 files, etc -def read_file(file): - df = pd.read_csv(file) - data = [] - num = [] - for index, row in df.iterrows(): - num.append(index) - #put header name of data you want in the hard brackets - data.append(row[' latency']) +def create_subplot (data): + file_name = data + with open (data) as csv_file: + next(csv_file) + csv_reader = csv.reader(csv_file, delimiter=',') + i = 0 + data = [] + num = [] + for row in csv_reader: + data.append((float)(row[0])) + num.append(i) + i+=1 ax = plt.subplot(subplotnum) - plt.plot(num, data) - + ax.set_title(file_name) + ax.plot(num, data) + plt.suptitle("Latency over time(ms)", fontsize=16) for file in file_names: - - read_file(file) + create_subplot(file) subplotnum += 1 -plt.savefig('line_plot.png') + +plt.subplots_adjust(hspace=.7) plt.show() +plt.savefig('line_plot.pdf', format='pdf') + + + From 1b8ae8c6c0bfbc56cda8e7c86882604dfafd19f6 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Fri, 12 Aug 2022 23:02:41 -0400 Subject: [PATCH 17/37] closed and open loop policies --- lib/httpClient.js | 105 ++++++++++++++++++++++++++++++++---- sample/request-generator.js | 9 ++-- 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index 65ed82f..a14815c 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -17,13 +17,17 @@ const Log = require('log'); const {HighResolutionTimer} = require('./hrtimer.js'); const headers = require('./headers.js'); const fs = require('fs'); +const { syncBuiltinESMExports } = require('module'); // globals const log = new Log('info'); const timeStamps = []; // added for gwloadtest timestamps -var url_list; //added for gwloadtest client behaviour +const req_url = []; // added for gwloadtest preserving urls +var url_list = null; //added for gwloadtest client behaviour var total; //added for gwloadtest client behaviour - +var prev; //added for gwloadtest client behaviour +var next = []; //added for gwloadtest client behaviour +var cur ; /** * Create a new HTTP client. @@ -137,17 +141,25 @@ class HttpClient { var cumulative_time = 0; var intr = this.params.rpsInterval *1000; var num_rquests =0; + if (this.params.mode == 'closed'){ // if the loop is closed then parse previous html for urls + this.parseHtml(prev); + var interval = 1000 * this.randomExp(rps); + cur += interval; + timeStamps[num_rquests] = cur; + num_rquests++; + setTimeout(() => this.makeRequest(), cur); // sets a timer for all the requests + } while (cumulative_time< intr) { var interval = 1000 * this.randomExp(rps); cumulative_time += interval; timeStamps[num_rquests] = cumulative_time; num_rquests++; - setTimeout(() => this.makeRequest(), cumulative_time); // sets a timer for all the requests + setTimeout(() => this.makeRequest(), cumulative_time); // sets a timer for all the requests } total = num_rquests; // starts the log file for each request let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; - let m = 'Index, timestamp, latency, status code \n'; + let m = 'Index, timestamp, latency, status code, url\n'; fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); } @@ -159,11 +171,12 @@ class HttpClient { //gwloadtest modification: read url list to make requested according to weights if (this.params.url_list){ try { + total = this.params.requestsPerSecond * this.params.rpsInterval; const data = fs.readFileSync(this.params.url_list, 'utf8'); var arr = this.fileToArray(data, ', ') url_list = arr; for (var i=0; i', i)){ // parse hyperlinks + var arr = [ temp.indexOf('', i)]; + table[num] = arr; + + if ( temp.indexOf('href="', i)>0){ + var start = temp.indexOf('href="', i); + var end = temp.indexOf('"', start+6); + //console.log("next: " + temp.substring(start+6, end)); + links[count] = temp.substring(start+6, end); + count++; + + } + i = temp.indexOf('/a>', i); + num++; + } + else if( temp.indexOf('0){ + var num = Math.floor(Math.random() * url_list.length); // choose a url randomly + if (url_list[num].weight>0){ //if a url has not handled its weight break, else choose a differnt url url_list[num].weight--; temp=url_list[num].url; + req_url[this.operation.requests-1] = temp; console.log(temp); break; } } + + } + else if (this.params.mode == 'closed'){ + //console.log("closed"); + //console.log(next); + if (next.length>0){ // check if prev request returned more links + + var num = Math.floor(Math.random() * next.length); + temp=next[num]; + req_url[this.operation.requests-1] = temp; + } + else { // if not, go to first link + temp = this.options; + req_url[this.operation.requests-1] = this.params.url; + } - console.log(num); - //hint use the max num of requests multiply weights by total - + } + else { temp = this.options; } @@ -336,7 +407,19 @@ class HttpClient { result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; result.startTime = timeStamps[index]; // stores the timestamps pf teh request added for gwloadtest - //console.log(result.body) + prev = result.body; + result.url = req_url[index]; + this.parseHtml(prev); + var intr = this.params.rpsInterval *1000; + if (this.params.mode == 'closed' && cur this.makeRequest(), cur); // sets a timer for all the requests + } + } diff --git a/sample/request-generator.js b/sample/request-generator.js index e2dbb8f..ad192f0 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -24,7 +24,9 @@ const options = { statusCallback: statusCallback, requestsPerSecond: rps, rpsInterval: rpsInter, - url_list: 'sample/url_list.txt' + //url_list: 'sample/url_list.txt', + mode: 'closed' // for the model where it follows the link open or closed + }; //the function called after every request is finished @@ -34,10 +36,11 @@ function statusCallback(error, result, latency) { console.log('Request index: ', result.requestIndex); console.log('Request elapsed milliseconds: ', result.requestElapsed); console.log('Code: ', result.statusCode); + console.log('URL: ', result.url); let n = result.requestElapsed.toFixed(); - let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + "\n"; - fs.writeFile(fileTitle, s, { flag: 'a+' }, err => {}); + let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + ", " + String(result.url) +"\n"; + fs.writeFileSync(fileTitle, s, { flag: 'a+' }, err => {}); dta[result.requestIndex]= result.requestElapsed; // store elpased for percentile calculation avg+=parseFloat(result.requestElapsed); // add to sum From 97d670f30a3574223a9923575ec592909e8370ff Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 22:13:29 -0400 Subject: [PATCH 18/37] comments + midsummer milestone fixes --- lib/httpClient.js | 189 ++++++++++++++++++------------------ sample/request-generator.js | 17 ++-- 2 files changed, 105 insertions(+), 101 deletions(-) diff --git a/lib/httpClient.js b/lib/httpClient.js index a14815c..433d9a0 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -21,13 +21,13 @@ const { syncBuiltinESMExports } = require('module'); // globals const log = new Log('info'); -const timeStamps = []; // added for gwloadtest timestamps -const req_url = []; // added for gwloadtest preserving urls -var url_list = null; //added for gwloadtest client behaviour -var total; //added for gwloadtest client behaviour -var prev; //added for gwloadtest client behaviour -var next = []; //added for gwloadtest client behaviour -var cur ; +const timeStamps = []; // added for gwloadtest timestamps start time of each request +const req_url = []; // added for gwloadtest recording the chosen url for each request +var url_list = null; //added for gwloadtest client behaviour used to store the file of the urls +var total; //added for gwloadtest client behaviour, stores the total number of requests sent +var prev; //added for gwloadtest client behaviour stores the html of the previous request +var next = []; //added for gwloadtest client behaviour, sstores a lidt of possible next urls to follow +var cumulative_time =0; //added to keep track of cumalative time for closed loop request /** * Create a new HTTP client. @@ -114,6 +114,10 @@ class HttpClient { log.debug('Options: %j', this.options); } + /** + * gwloadtest: returns a randomly distributed exponential number + * based on the given rps + */ randomExp(rps){ let v = Number(rps); v = -1/v; @@ -127,66 +131,78 @@ class HttpClient { * Start the HTTP client. */ start() { - if (this.params.rpsInterval) { - const rps = this.params.requestsPerSecond; - if (this.params.agentKeepAlive) { - this.options.agent.maxSockets = 10 + rps; - } - // stop the old requesttimer - if (this.requestTimer !== undefined) { + if (this.params.clientMode == 'open'){ //if this is an open loop client request model + //gwloadtest modification: read url list to make requested according to weights + if (this.params.urlList){ + try { + total = this.params.requestsPerSecond * this.params.rpsInterval; + const data = fs.readFileSync(this.params.urlList, 'utf8'); + var arr = this.fileToArray(data, ', ') + console.log(arr); + url_list = arr; + for (var i=0; i this.makeRequest(), cumulative_time); // sets a timer for the first request only + } + else{ // if this is an open loop model, make the requests + if (this.params.rpsInterval) { // if a time interval is given, use exponentially distributed numbers + const rps = this.params.requestsPerSecond; + if (this.params.agentKeepAlive) { + this.options.agent.maxSockets = 10 + rps; + } + + // stop the old requesttimer + if (this.requestTimer !== undefined) { this.requestTimer.stop(); - } - // Modification: Replace the fixed interval by exponential random interval - // which follows the poisson distribution - var cumulative_time = 0; + } + + var total_time = 0; var intr = this.params.rpsInterval *1000; var num_rquests =0; - if (this.params.mode == 'closed'){ // if the loop is closed then parse previous html for urls - this.parseHtml(prev); - var interval = 1000 * this.randomExp(rps); - cur += interval; - timeStamps[num_rquests] = cur; - num_rquests++; - setTimeout(() => this.makeRequest(), cur); // sets a timer for all the requests - } - while (cumulative_time< intr) { + while (total_time< intr) { var interval = 1000 * this.randomExp(rps); - cumulative_time += interval; - timeStamps[num_rquests] = cumulative_time; + total_time += interval; + timeStamps[num_rquests] =total_time; num_rquests++; - setTimeout(() => this.makeRequest(), cumulative_time); // sets a timer for all the requests + setTimeout(() => this.makeRequest(), total_time); // sets a timer for all the requests } - total = num_rquests; - // starts the log file for each request - let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; - let m = 'Index, timestamp, latency, status code, url\n'; - fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); - + } + else{ // if no time interval given, use constant time intervals (original loadtest method) + const interval = 1000 / this.params.requestsPerSecond; + // start new request timer + this.requestTimer = new HighResolutionTimer(interval, () => this.makeRequest()); + } } - else{ - const interval = 1000 / this.params.requestsPerSecond; - // start new request timer - this.requestTimer = new HighResolutionTimer(interval, () => this.makeRequest()); - } - //gwloadtest modification: read url list to make requested according to weights - if (this.params.url_list){ - try { - total = this.params.requestsPerSecond * this.params.rpsInterval; - const data = fs.readFileSync(this.params.url_list, 'utf8'); - var arr = this.fileToArray(data, ', ') - url_list = arr; - for (var i=0; i {}); } + /** + * gwloadtest: takes in a text/csv file and returns it as an array + */ fileToArray(str, delimiter = ",") { // slice from start of text to the first \n index // use split to create an array from string by delimiter @@ -207,16 +223,18 @@ class HttpClient { // return the array return arr; - } - + } + + /** + * gwloadtest: takes in a text html and returns an array of all links found as + * hyperlinks + */ parseHtml( prev ){ var table = []; var links = []; var temp = String(prev); var num = 0; var count = 0; - - //console.log("string length : " + temp.length); for (var i = 0; i', i)){ // parse hyperlinks @@ -226,7 +244,6 @@ class HttpClient { if ( temp.indexOf('href="', i)>0){ var start = temp.indexOf('href="', i); var end = temp.indexOf('"', start+6); - //console.log("next: " + temp.substring(start+6, end)); links[count] = temp.substring(start+6, end); count++; @@ -241,17 +258,9 @@ class HttpClient { } next = links; - console.log(next); - } - - wait(ms) { - var start = Date.now(), - now = start; - while (now - start < ms) { - now = Date.now(); - } } + /** * Stop the HTTP client. */ @@ -308,10 +317,11 @@ class HttpClient { if (typeof this.params.requestGenerator == 'function') { request = this.params.requestGenerator(this.params, this.options, lib.request, this.getConnect(id, requestFinished, this.params.contentInspector)); } else { + //gwloadtest modification - //check if file passed in and if true use weights to send a different url each time + //check if requests need to follow a client mode var temp; - if (this.params.url_list){ + if (this.params.clientMode == 'open'){ //choose url here according to weight while (true){ var num = Math.floor(Math.random() * url_list.length); // choose a url randomly @@ -319,15 +329,14 @@ class HttpClient { url_list[num].weight--; temp=url_list[num].url; req_url[this.operation.requests-1] = temp; - console.log(temp); break; } } } - else if (this.params.mode == 'closed'){ - //console.log("closed"); - //console.log(next); + + else if (this.params.clientMode == 'closed'){ + if (next.length>0){ // check if prev request returned more links var num = Math.floor(Math.random() * next.length); @@ -344,6 +353,7 @@ class HttpClient { else { temp = this.options; + req_url[this.operation.requests-1] = this.params.url; } request = lib.request(temp, this.getConnect(id, requestFinished, this.params.contentInspector)); @@ -387,42 +397,35 @@ class HttpClient { } const elapsed = this.operation.latency.end(id, errorCode); - - - - - if (elapsed < 0) { // not found or not running return; } - const index = this.operation.latency.getRequestIndex(id); - - - + const index = this.operation.latency.getRequestIndex(id); if (result) { result.requestElapsed = elapsed; result.requestIndex = index; result.instanceIndex = this.operation.instanceIndex; - result.startTime = timeStamps[index]; // stores the timestamps pf teh request added for gwloadtest + result.startTime = timeStamps[index]; // stores the timestamps of the request added for gwloadtest prev = result.body; result.url = req_url[index]; this.parseHtml(prev); var intr = this.params.rpsInterval *1000; - if (this.params.mode == 'closed' && cur this.makeRequest(), cur); // sets a timer for all the requests + cumulative_time += interval; + timeStamps[total] = cumulative_time; + total++; + setTimeout(() => this.makeRequest(), interval); // sets a timer for all the requests } } - let callback; if (!this.params.requestsPerSecond) { callback = this.makeRequest.bind(this); diff --git a/sample/request-generator.js b/sample/request-generator.js index ad192f0..ddd469c 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -1,4 +1,3 @@ - // requires const loadtest = require('../lib/loadtest.js'); const testserver = require('../lib/testserver.js'); @@ -24,13 +23,13 @@ const options = { statusCallback: statusCallback, requestsPerSecond: rps, rpsInterval: rpsInter, - //url_list: 'sample/url_list.txt', - mode: 'closed' // for the model where it follows the link open or closed + urlList: 'sample/url_list.txt',// an example of passing in a list of urls with weights by passing in the file title + clientMode: 'open' //passed in to activate gwloadtest modifications 'closed' for closed loop requests and 'open' for open loop requests }; //the function called after every request is finished -function statusCallback(error, result, latency) { +function statusCallback(error, result, latency) { console.log('----'); console.log('Timestamp: ', result.startTime.toFixed(2)); console.log('Request index: ', result.requestIndex); @@ -40,19 +39,21 @@ function statusCallback(error, result, latency) { let n = result.requestElapsed.toFixed(); let s = result.requestIndex + ", " +result.startTime.toFixed(2) + ", " + n.toString() + ", " + result.statusCode + ", " + String(result.url) +"\n"; - fs.writeFileSync(fileTitle, s, { flag: 'a+' }, err => {}); + + fs.writeFileSync(fileTitle, s, { flag: 'a+' }, err => {}); //write to the log file + dta[result.requestIndex]= result.requestElapsed; // store elpased for percentile calculation avg+=parseFloat(result.requestElapsed); // add to sum if (result.requestIndex==0){ - slowest =result.requestElapsed; + slowest = result.requestElapsed; fastest = result.requestElapsed; } else{ if (result.requestElapsedslowest){ @@ -60,13 +61,13 @@ function statusCallback(error, result, latency) { } } - if ( result.statusCode>299){ errs++; } if ( result.startTime>rpsInter*1000){ max = result.requestIndex +1; + // print summary after last request let f = "Summary: " + '\n'; f = f + 'total time: '; From 70e9d03572e6666eeb28e1b02001b5c29a818ede Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 22:21:06 -0400 Subject: [PATCH 19/37] scripts read command line arguments --- scripts/99ile.py | 3 ++- scripts/cdf.py | 3 ++- scripts/histogram.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/99ile.py b/scripts/99ile.py index 3903969..bf5bf82 100644 --- a/scripts/99ile.py +++ b/scripts/99ile.py @@ -1,8 +1,9 @@ import csv +import sys import matplotlib.pyplot as plt import pandas as pd -df = pd.read_csv("sample/rps-99ile.csv") +df = pd.read_csv(sys.argv[0]) print(df) data = [] num = [] diff --git a/scripts/cdf.py b/scripts/cdf.py index 8e4cb8e..f172bd5 100644 --- a/scripts/cdf.py +++ b/scripts/cdf.py @@ -1,5 +1,6 @@ import pandas as pd import csv +import sys import matplotlib.pyplot as plt import numpy as np import warnings @@ -20,7 +21,7 @@ #Change path -df = pd.read_csv('sample/log-rps-100-iv-10.csv') +df = pd.read_csv(sys.argv[0]) #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows diff --git a/scripts/histogram.py b/scripts/histogram.py index 9701b2b..ba3eb4f 100644 --- a/scripts/histogram.py +++ b/scripts/histogram.py @@ -1,5 +1,6 @@ import pandas as pd import csv +import sys import matplotlib.pyplot as plt import numpy as np @@ -17,7 +18,7 @@ #********************************************************************** #Change path -df = pd.read_csv('sample/log-rps-100-iv-10.csv') +df = pd.read_csv(sys.argv[0]) #********************************************************************** #df.iterrows returns series for each row it does not preserve data types across the rows From 5bd7209225f13a7cf7248c5a3deaa8d87421bd17 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:02:05 -0400 Subject: [PATCH 20/37] readme outline + req-gen no automation fix --- README.md | 30 ++++++++++++++++++++++++++++++ lib/httpClient.js | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b9c349..b5ed836 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,36 @@ [![Package quality](http://packagequality.com/badge/loadtest.png)](http://packagequality.com/#?package=loadtest) +# Gwloadtest + +Gwloadtest modified loadtest to creat load tests that imitate client-behavior more closely by using randomly distributed time intervals between requests and allowing for more random url access behavior. + +## How to Use + + 1. Install Node.js, clone this repository, and open the newly cloned directory: + git clone https://github.com/gwcloudlab/gwloadtest.git + sudo apt update + sudo apt-get install -y nodejs + cd ~/gwloadtest + npm install + 2. Modify sample/request-generator.js with desired options + 3. Run the following command to run the test: + node sample/request-generator.js + +## Modfifications + +### Poisson Interarrival time + +### Logs and Summaries + +## Additions + +### Client Modes + +### graphing scripts + +### Automation Script + # loadtest Runs a load test on the selected HTTP or WebSockets URL. The API allows for easy integration in your own tests. diff --git a/lib/httpClient.js b/lib/httpClient.js index 433d9a0..83ddfc2 100644 --- a/lib/httpClient.js +++ b/lib/httpClient.js @@ -165,7 +165,7 @@ class HttpClient { } else{ // if this is an open loop model, make the requests if (this.params.rpsInterval) { // if a time interval is given, use exponentially distributed numbers - const rps = this.params.requestsPerSecond; + var rps = this.params.requestsPerSecond; if (this.params.agentKeepAlive) { this.options.agent.maxSockets = 10 + rps; } @@ -195,6 +195,7 @@ class HttpClient { //gwloadtest: create log files var intr = this.params.rpsInterval *1000; + var rps = this.params.requestsPerSecond; let fileTitle = "sample/log-rps-"+rps+"-iv-"+intr/1000 + ".csv"; let m = 'Index, timestamp, latency, status code, url\n'; fs.writeFile(fileTitle, m, { flag: 'w' }, err => {}); From 591d4910609e6f6a6ba51b75a56540126a7f4d0f Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:48:24 -0400 Subject: [PATCH 21/37] full initial readme --- README.md | 56 +++++++++++++++++++++++++++++++++++++ sample/request-generator.js | 18 ++++++------ 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b5ed836..99002af 100644 --- a/README.md +++ b/README.md @@ -12,29 +12,85 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. Install Node.js, clone this repository, and open the newly cloned directory: + ```sh git clone https://github.com/gwcloudlab/gwloadtest.git sudo apt update sudo apt-get install -y nodejs cd ~/gwloadtest npm install + ``` 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: + ```sh node sample/request-generator.js + ``` ## Modfifications ### Poisson Interarrival time +Given a requests per second rate and a time inerval for the load test, gwloadtests send requests at randomly distributed time intervals. + ### Logs and Summaries +Gwloadtest prints a summary text file along with a log file that includes the index, timestamp, latency, status code, and url of every request. + ## Additions ### Client Modes +In an attempt to resmeble client behavior, gwloadtest carries two client behavior policies. + +#### Closed Loop + +The client thread sends a request and waits for it to return an html, which it then parses for hyperlinks and randomly selects a link so send the next request to. If no links are found, it sends the next request to the options url. + +usage example: +```javascript + const options = { + url: 'http://127.0.0.1:5000', + statusCallback: statusCallback, + requestsPerSecond: 10, + rpsInterval: 10, + clientMode: 'closed' + }; +``` + +#### Open Loop + +The client thread sends requests to multiple links according to the weights given in a file. A file must be passed in along with selecting the open clientMode. + +usage example: +```javascript + const options = { + url: 'http://127.0.0.1:5000', + statusCallback: statusCallback, + requestsPerSecond: 10, + rpsInterval: 10, + urlList: 'sample/url_list.txt', //include title of file here + clientMode: 'open' + }; +``` +sample/url_list.txt: +``` + url, weight + http://127.0.0.1:5000, 0.80 + http://127.0.0.1:5000/test1, 0.20 +``` + ### graphing scripts +Gwloadtest carries 4 types of graphing scripts in the scripts file, which can be run on the Gwloadtest generated log files. + 1. 99th percentile latency vs. requests per second rate + 2. number of occurences vs latency histogram + 3. latency over time line graph + 4. cdf vs response time + + ### Automation Script +For research purposes, automation/run.py can run multiple tests given a list of requests per second rates. + # loadtest Runs a load test on the selected HTTP or WebSockets URL. The API allows for easy integration in your own tests. diff --git a/sample/request-generator.js b/sample/request-generator.js index ddd469c..02fa776 100644 --- a/sample/request-generator.js +++ b/sample/request-generator.js @@ -5,8 +5,9 @@ const args = require('minimist')(process.argv.slice(2)); const fs = require('fs'); -rps = args.rps; -rpsInter= args.interval; +//uncomment to use automation script +//rps = args.rps; +//rpsInter= args.interval; const dta = []; var errs= 0; var slowest; @@ -14,20 +15,19 @@ var fastest; var max; var avg =0; - -let fileTitle = "sample/log-rps-"+rps+"-iv-"+rpsInter+ ".csv"; -let fileTitle2 = "sample/sum-rps-"+rps+"-iv-"+rpsInter + ".txt"; - const options = { url: 'http://127.0.0.1:5000', statusCallback: statusCallback, - requestsPerSecond: rps, - rpsInterval: rpsInter, + requestsPerSecond: 10, // replace number with rps for automation script + rpsInterval: 10, //replace number with rpsInter for automation script urlList: 'sample/url_list.txt',// an example of passing in a list of urls with weights by passing in the file title clientMode: 'open' //passed in to activate gwloadtest modifications 'closed' for closed loop requests and 'open' for open loop requests }; +let fileTitle = "sample/log-rps-"+options.requestsPerSecond+"-iv-"+options.rpsInterval+ ".csv"; +let fileTitle2 = "sample/sum-rps-"+options.requestsPerSecond+"-iv-"+options.rpsInterval + ".txt"; + //the function called after every request is finished function statusCallback(error, result, latency) { console.log('----'); @@ -65,7 +65,7 @@ function statusCallback(error, result, latency) { errs++; } - if ( result.startTime>rpsInter*1000){ + if ( result.startTime>options.rpsInterval*1000){ max = result.requestIndex +1; // print summary after last request From 678233dda00dbbc737d278b3d80d5e989cc892c9 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:50:18 -0400 Subject: [PATCH 22/37] fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99002af..e2dc1cc 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo sudo apt-get install -y nodejs cd ~/gwloadtest npm install - ``` + ``` 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: ```sh From c00eda3e7c401d3ec1134039e6b73e44cf6a6016 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:51:15 -0400 Subject: [PATCH 23/37] fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2dc1cc..b70ed64 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. Install Node.js, clone this repository, and open the newly cloned directory: - ```sh + ``` git clone https://github.com/gwcloudlab/gwloadtest.git sudo apt update sudo apt-get install -y nodejs From 9a1ebf2621c65d657e8f1bd1dab09d257720b39b Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:51:50 -0400 Subject: [PATCH 24/37] fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b70ed64..32a519e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. Install Node.js, clone this repository, and open the newly cloned directory: - ``` + ```sh git clone https://github.com/gwcloudlab/gwloadtest.git sudo apt update sudo apt-get install -y nodejs From 5d4e36ac744c0dfc749f706e57d7787ce1c1b720 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:53:48 -0400 Subject: [PATCH 25/37] readme fix --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 32a519e..bc4b0d0 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. Install Node.js, clone this repository, and open the newly cloned directory: ```sh - git clone https://github.com/gwcloudlab/gwloadtest.git - sudo apt update - sudo apt-get install -y nodejs - cd ~/gwloadtest - npm install + git clone https://github.com/gwcloudlab/gwloadtest.git + sudo apt update + sudo apt-get install -y nodejs + cd ~/gwloadtest + npm install ``` 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: From e5a95dc91053086832f24fe252f2de2d48ddae46 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:55:50 -0400 Subject: [PATCH 26/37] readme --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bc4b0d0..a94ec75 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,13 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. Install Node.js, clone this repository, and open the newly cloned directory: + ```sh - git clone https://github.com/gwcloudlab/gwloadtest.git - sudo apt update - sudo apt-get install -y nodejs - cd ~/gwloadtest - npm install + git clone https://github.com/gwcloudlab/gwloadtest.git + sudo apt update + sudo apt-get install -y nodejs + cd ~/gwloadtest + npm install ``` 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: From 52dbd706eb1d3c8d45853539869135095ee1d5a5 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:56:48 -0400 Subject: [PATCH 27/37] fix --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a94ec75..8f7ffdc 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,14 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use - 1. Install Node.js, clone this repository, and open the newly cloned directory: + 1. Install Node.js, clone this repository, and open the newly cloned directory by running the following commands: - ```sh git clone https://github.com/gwcloudlab/gwloadtest.git sudo apt update sudo apt-get install -y nodejs cd ~/gwloadtest npm install - ``` + 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: ```sh From fa3a1506a227eb1005f9a20d3d08924c6e7cb187 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:58:15 -0400 Subject: [PATCH 28/37] readme formatting --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8f7ffdc..88f8080 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. Install Node.js, clone this repository, and open the newly cloned directory by running the following commands: - git clone https://github.com/gwcloudlab/gwloadtest.git - sudo apt update - sudo apt-get install -y nodejs - cd ~/gwloadtest - npm install + git clone https://github.com/gwcloudlab/gwloadtest.git + sudo apt update + sudo apt-get install -y nodejs + cd ~/gwloadtest + npm install 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: From b955d993e9f6f6cd0eb2476fda1505c8fc90c4f2 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Mon, 15 Aug 2022 23:59:50 -0400 Subject: [PATCH 29/37] formatting --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 88f8080..9a1dd4c 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,9 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. Install Node.js, clone this repository, and open the newly cloned directory by running the following commands: - + ```sh git clone https://github.com/gwcloudlab/gwloadtest.git - sudo apt update - sudo apt-get install -y nodejs - cd ~/gwloadtest - npm install + ``` 2. Modify sample/request-generator.js with desired options 3. Run the following command to run the test: From ec16d8ec02926c447e7e93158cb923fd96bc2404 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:07:20 -0400 Subject: [PATCH 30/37] sh file --- README.md | 11 +++++++---- install_node.sh | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 install_node.sh diff --git a/README.md b/README.md index 9a1dd4c..c15e229 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,16 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use - 1. Install Node.js, clone this repository, and open the newly cloned directory by running the following commands: + 1. clone this repository, and open the newly cloned directory: ```sh git clone https://github.com/gwcloudlab/gwloadtest.git ``` - - 2. Modify sample/request-generator.js with desired options - 3. Run the following command to run the test: + 2. Install Node.js and npm by by running the following commands: + ```sh + ./install_node.sh + ``` + 3. Modify sample/request-generator.js with desired options + 4. Run the following command to run the test: ```sh node sample/request-generator.js ``` diff --git a/install_node.sh b/install_node.sh new file mode 100644 index 0000000..e36787a --- /dev/null +++ b/install_node.sh @@ -0,0 +1,4 @@ +sudo apt update +sudo apt-get install -y nodejs +cd ~/gwloadtest +npm install \ No newline at end of file From c55e10056caaad32dd7aa0dc1d5cfd3d9c7a2d20 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:08:42 -0400 Subject: [PATCH 31/37] spacing --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c15e229..f27bf1c 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,13 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. clone this repository, and open the newly cloned directory: - ```sh + ```sh git clone https://github.com/gwcloudlab/gwloadtest.git - ``` + ``` 2. Install Node.js and npm by by running the following commands: - ```sh + ```sh ./install_node.sh - ``` + ``` 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: ```sh From eeb885ec28fc8aa37fd7334ada6aae355ef485c2 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:09:25 -0400 Subject: [PATCH 32/37] spacing --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f27bf1c..629d2e8 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,16 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. clone this repository, and open the newly cloned directory: ```sh - git clone https://github.com/gwcloudlab/gwloadtest.git + git clone https://github.com/gwcloudlab/gwloadtest.git ``` 2. Install Node.js and npm by by running the following commands: ```sh - ./install_node.sh + ./install_node.sh ``` 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: ```sh - node sample/request-generator.js + node sample/request-generator.js ``` ## Modfifications From 1b185d7ccd2d8e2867bc9d7e658afca248a433a8 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:10:07 -0400 Subject: [PATCH 33/37] spacing fix --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 629d2e8..a4b92d4 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,12 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ```sh git clone https://github.com/gwcloudlab/gwloadtest.git ``` + 2. Install Node.js and npm by by running the following commands: ```sh ./install_node.sh ``` + 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: ```sh From 66a16674a5373d78c339ae7bfa4ed564b29522a8 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:11:31 -0400 Subject: [PATCH 34/37] formatting --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a4b92d4..5c98571 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,20 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo ## How to Use 1. clone this repository, and open the newly cloned directory: + ```sh git clone https://github.com/gwcloudlab/gwloadtest.git ``` 2. Install Node.js and npm by by running the following commands: + ```sh ./install_node.sh ``` - + 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: + ```sh node sample/request-generator.js ``` From d5f45b39b0baa283c1b637a16cd9477c4777e647 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:12:26 -0400 Subject: [PATCH 35/37] fix --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5c98571..ccc60cb 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,18 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. clone this repository, and open the newly cloned directory: - ```sh git clone https://github.com/gwcloudlab/gwloadtest.git - ``` + 2. Install Node.js and npm by by running the following commands: - ```sh ./install_node.sh - ``` 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: - - ```sh + node sample/request-generator.js - ``` + ## Modfifications From 18f6da6b663d2e8be1d2d6364a5608e0edcbe808 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:13:38 -0400 Subject: [PATCH 36/37] fix --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ccc60cb..d8137d7 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,17 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. clone this repository, and open the newly cloned directory: - git clone https://github.com/gwcloudlab/gwloadtest.git + git clone https://github.com/gwcloudlab/gwloadtest.git 2. Install Node.js and npm by by running the following commands: - ./install_node.sh + ./install_node.sh 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: - node sample/request-generator.js + node sample/request-generator.js ## Modfifications From 5aa7d50a4da6fb39f43257a7409aad99ffe26c02 Mon Sep 17 00:00:00 2001 From: Dania Abdalla Date: Tue, 16 Aug 2022 00:15:36 -0400 Subject: [PATCH 37/37] fix --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d8137d7..03d8f8f 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,22 @@ Gwloadtest modified loadtest to creat load tests that imitate client-behavior mo 1. clone this repository, and open the newly cloned directory: - git clone https://github.com/gwcloudlab/gwloadtest.git - +``` + git clone https://github.com/gwcloudlab/gwloadtest.git +``` 2. Install Node.js and npm by by running the following commands: - ./install_node.sh +``` + ./install_node.sh +``` 3. Modify sample/request-generator.js with desired options 4. Run the following command to run the test: - node sample/request-generator.js - - +``` + node sample/request-generator.js +``` ## Modfifications ### Poisson Interarrival time