SlideShare a Scribd company logo
Or getting paid to DoS your own systems
Load Testing with
RedLine13
Jason Lotito
What is Load Testing?
Load testing is the process of putting demand on
a software system or computing device and
measuring its response.
Load testing is performed to determine a
system's behavior under both normal and
anticipated peak load conditions.
It helps to identify the maximum operating
capacity of an application as well as any
bottlenecks and determine which element is
causing degradation.
What about Stress Testing?
Stress testing focuses on throughput.
Load testing focuses on response times.
Both can be performed at the same time.
Load Testing
• Putting demand on a system
• Measuring the response
• Determine behavior under
load
• Determine maximum operating
capacity
• Bottlenecks
Other Load Testing Tools
• ApacheBench (ab)
• Apache JMeter
• siege
• BlazeMeter
Why RedLine13?
• Simple, up and running in little time
• Inexpensive, you pay for what you use
• Scriptable, so you have complete control over your
tests
• I know Rich
RedLine13 has a bunch of features you can read
about on the website. I’m really here to talk to
you about the cool stuff I do with RedLine13.
The Basics of Load Testing
The Basics of RedLine13
This is another subtitle that I’m
apparently supposed to use, in place of
the title, and the super subtitle above
the title.
Preparing for Load Testing
Need
• Production-level systems to test against
• Monitoring
• CPU, memory, I/O, etc.
• Application dashboards
• Logging
• Automated systems to deploy
• Dedicated people
• A time to test
Learning
• Set goals, e.g.
• 50ms
• 500rps
• Test monitoring
• Scaling
• What happens to the app under load?
• What slows down first?
As Load Tester, you are responsible for…
• Ensuring those involved with the system under test are
aware and available
• Putting the system under test under load
• Completely destroying the system under load
• Providing a clear and concise write up of exactly what
occurred
• Take charge! It’s fun!
Ramp Up Time
• Start at what you expect normal traffic to be
• 500rps
• Start a second test that is just the burst traffic
• 900rps
• Ramps up over 20 mins
• Lasts 40 mins at peak
• Ramps down over 20 mins
Reporting
Reporting Results: Shortest Version
• 99% @ 59ms
Reporting Results: Short Version
• Short version: During an hour starting with 0rps to 1400 rps
in the first 10 minutes....
• ...when starting with 5 instances and scaling to 11
instances, the response time were: 50% 23ms, 75% 54ms,
95% 303ms, and 99% 1069ms.
• ...when starting with 11 instances, the response times
were: 50% 16ms, 75% 24ms, 95% 45ms, and 99% 59ms.
Reporting Results: Detailed Version
• Provide more information
• Results
• Story driven
• Have data supporting results prepared in case
• Account for changes such as auto-scaling
• With auto-scaling: 99% at 1069ms
• Without auto-scaling: 99% at 59ms
Testing elasticsearch on c3.4xlarge
Detailed Reporting
Also included in this report was a link to
the actual GitHub repository. Make sure
you are keeping your load tests in
version control!
Tag your load test in git
Associate the tag with a Load Test,
so you can replay any load test easily
PHP & Node.js
We’ll be using Node.js for our examples
Writing a RedLine13 Custom Load Test in Node.js
• Uploading a *.tar.gz/*.zip file
• npm install is run
• Expects a CustomTest.js file in root directory
• CustomTest.js should export a ‘class’
• Will create a new object from
• class(redLine, testNum, rand, config)
• Will call runTest() on object of class
{
"name": "reloaded",
"version": "1.0.0",
"description": "Recommendation Engine Load Tester",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "node app.js",
"build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' --
exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *"
},
"author": "Jason Lotito <jlotito@meetme.com>",
"license": "ISC",
"dependencies": {
"async": "^1.3.0",
"elasticsearch": "^5.0.0",
"lodash": "^3.10.0",
package.json
{
"name": "reloaded",
"version": "1.0.0",
"description": "Recommendation Engine Load Tester",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "node app.js",
"build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' --
exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *"
},
"author": "Jason Lotito <jlotito@meetme.com>",
"license": "ISC",
"dependencies": {
"async": "^1.3.0",
"elasticsearch": "^5.0.0",
"lodash": "^3.10.0",
package.json
{
"name": "reloaded",
"version": "1.0.0",
"description": "Recommendation Engine Load Tester",
"main": "app.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "node app.js",
"build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' --
exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *"
},
"author": "Jason Lotito <jlotito@meetme.com>",
"license": "ISC",
"dependencies": {
"async": "^1.3.0",
"elasticsearch": "^5.0.0",
"lodash": "^3.10.0",
package.json
var Test = require('./CustomTest');
var rl = require('./lib/RedLine');
(new Test(new rl.RedLine, 55)).runTest(function(){
console.log( "test complete");
});
app.js
var Test = require('./CustomTest');
var rl = require('./lib/RedLine');
(new Test(new rl.RedLine, 55)).runTest(function(){
console.log( "test complete");
});
app.js
var Test = require('./CustomTest');
var rl = require('./lib/RedLine');
(new Test(new rl.RedLine, 55)).runTest(function(){
console.log( "test complete");
});
app.js
var Test = require('./CustomTest');
var rl = require('./lib/RedLine');
(new Test(new rl.RedLine, 55)).runTest(function(){
console.log( "test complete");
});
app.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
function RedLine(){}
RedLine.prototype.recordPageTime = function(ts, time){};
RedLine.prototype.recordURLPageLoad = function(url, ts, time){};
RedLine.prototype.recordDownloadSize = function(kb){};
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
RedLine.js
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
Timer.prototype.start = function ()
{
return new ActiveTimer( Date.now(), this.url, this.redLine );
};
function ActiveTimer( startTime, url, redLineAPI )
{
RedLine.js
RedLine.prototype.recordError = function(error){console.log(error)};
RedLine.prototype.recordProgress = function(testNum, percent){};
function Timer( url, redLineAPI )
{
this.url = url;
this.redLine = redLineAPI;
}
Timer.prototype.start = function ()
{
return new ActiveTimer( Date.now(), this.url, this.redLine );
};
function ActiveTimer( startTime, url, redLineAPI )
{
RedLine.js
Timer.prototype.start = function ()
{
return new ActiveTimer( Date.now(), this.url, this.redLine );
};
function ActiveTimer( startTime, url, redLineAPI )
{
this.endTime = 0;
this.startTime = startTime;
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
Timer: Timer
};
RedLine.js
var async = require( 'async' );
var sleep = require( 'sleep' );
var Timer = require( './lib/RedLine' ).Timer;
var Test = require( './lib/Test' );
// Load Testing Options
var MINUTES_TO_RUN = 60;
var MAX_MINUTES_TO_WAIT_BEFORE_START = 10;
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
CustomTest.js
var async = require( 'async' );
var sleep = require( 'sleep' );
var Timer = require( './lib/RedLine' ).Timer;
var Test = require( './lib/Test' );
// Load Testing Options
var MINUTES_TO_RUN = 60;
var MAX_MINUTES_TO_WAIT_BEFORE_START = 10;
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
CustomTest.js
var sleep = require( 'sleep' );
var Timer = require( './lib/RedLine' ).Timer;
var Test = require( './lib/Test' );
// Load Testing Options
var MINUTES_TO_RUN = 60;
var MAX_MINUTES_TO_WAIT_BEFORE_START = 10;
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
function rand( low, high )
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
CustomTest.js
var sleep = require( 'sleep' );
var Timer = require( './lib/RedLine' ).Timer;
var Test = require( './lib/Test' );
// Load Testing Options
var MINUTES_TO_RUN = 60;
var MAX_MINUTES_TO_WAIT_BEFORE_START = 10;
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
function rand( low, high )
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
CustomTest.js
var sleep = require( 'sleep' );
var Timer = require( './lib/RedLine' ).Timer;
var Test = require( './lib/Test' );
// Load Testing Options
var MINUTES_TO_RUN = 60;
var MAX_MINUTES_TO_WAIT_BEFORE_START = 10;
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
function rand( low, high )
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
CustomTest.js
var MIN_MINUTES_TO_WAIT_BEFORE_START = 0;
// Normally don't need to change
var RUN_EVERY_MILLISECONDS = 1000;
function rand( low, high )
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
CustomTest.js
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
CustomTest.js
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
CustomTest.js
{
return Math.floor( Math.random() * (high - low + 1) + low );
}
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
CustomTest.js
}
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
{
var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60,
MAX_MINUTES_TO_WAIT_BEFORE_START * 60 );
CustomTest.js
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
{
var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60,
MAX_MINUTES_TO_WAIT_BEFORE_START * 60 );
console.log( Date.now() + " - Sleeping for " + sleepInSeconds );
sleep.sleep( sleepInSeconds );
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
CustomTest.js
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
{
var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60,
MAX_MINUTES_TO_WAIT_BEFORE_START * 60 );
console.log( Date.now() + " - Sleeping for " + sleepInSeconds );
sleep.sleep( sleepInSeconds );
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
CustomTest.js
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
{
var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60,
MAX_MINUTES_TO_WAIT_BEFORE_START * 60 );
console.log( Date.now() + " - Sleeping for " + sleepInSeconds );
sleep.sleep( sleepInSeconds );
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
CustomTest.js
function Reloaded( rl, testNum, rand, config )
{
this.rl = rl;
this.testNum = testNum;
this.rand = rand;
this.config = config;
this.test = new Test();
this.rampUp();
}
Reloaded.prototype.rampUp = function ()
{
var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60,
MAX_MINUTES_TO_WAIT_BEFORE_START * 60 );
console.log( Date.now() + " - Sleeping for " + sleepInSeconds );
CustomTest.js
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
var max = 60 * MINUTES_TO_RUN;
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
CustomTest.js
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
var max = 60 * MINUTES_TO_RUN;
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
CustomTest.js
console.log( Date.now() + " - Done sleeping for " + sleepInSeconds );
};
Reloaded.prototype.runTest = function ( finished )
{
var timer = new Timer( 'test', this.rl );
var max = 60 * MINUTES_TO_RUN;
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
CustomTest.js
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
CustomTest.js
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
CustomTest.js
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
CustomTest.js
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
CustomTest.js
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
CustomTest.js
var max = 60 * MINUTES_TO_RUN;
async.timesSeries( max, function ( n, next )
{
var activeTimer = new timer.start();
var timeDiff = 0;
this.test.runATest( function ( err )
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
CustomTest.js
{
if ( err )
{
this.rl.recordError( err.message );
}
timeDiff = activeTimer.stop();
setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff );
}.bind( this ) );
}.bind( this ), function ()
{
finished( true );
} );
};
CustomTest.js
Now, let’s hack logging
By default,RedLine doesn’t support logging
through the web UI
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
this.redLine = redLineAPI;
this.url = url;
}
ActiveTimer.prototype.stop = function ()
{
this.endTime = Date.now();
var timeDiff = this.endTime - this.startTime;
this.redLine.recordError(timeDiff);
this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 );
this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 );
return timeDiff;
};
module.exports= {
RedLine: RedLine,
RedLine.js
Response Times
Counts
19 requests at 27ms
With this we can get percentiles
Of course, the pro version offers this for PHP
You can use error reporting to
simulate real time logging
The important thing here is…
Writing Custom Load Tests
Things to Keep In Mind
• Understand expected usage
• X% of users using the app while
• Y% are chatting with one another
• Users are logging in
• Creating accounts
• Backend systems
• Determine what’s important
Things to Keep In Mind
• User input
• Random filters
• Weighted filters
• Cached results are expected
• Client constraints
Things to Keep In Mind
• User flow through service
• Try to understand how users use the app
• Script should try to mimic
Things to Keep In Mind
• Be care about testing a single system
• System will have logging
• System will have backend services
• You’d be surprised what can cause failure
• A Load Test helps you learn before it’s in production
Things to Keep In Mind
• User interaction
• MeetMe is social, so we’ve load tested chatting
• 1 test per 2 users, both chatting with one another
• Story time!
Things to Keep In Mind
• Have developers available
• Better, have developers with you when load testing
• Find a problem, Fix it, Reroll app, Rerun test
• FFRR
• I just made that up
• Don’t use it.
Things to Keep In Mind
• Start testing from your laptop
• Seriously, my MacBook Air could bring down Erlang
services
• Database indexes are a thing
• While running a load test, you can run a single client
form your laptop
Things to Keep In Mind
• Someone should be testing the app/service as well
• Response times are only a number
• What does 50ms vs 300ms response times feel to the
user
• What impact does 2x/3x/4x load have
• When auto-scaling, how does the client handle
Things to Keep In Mind
• Review how the client is using the API
• Review how the API developer expects the client to use
the API
• Model after what the client is doing
• Call out differences early
Learn
Most importantly…
In Russia, Load tests You!
Good load tests will teach you things
you didn’t know about your systems.
Great load tests will help you solve those problems
before they become production problems.
Load Testing with RedLine13
Thanks!
@jasonlotito
jasonlotito.com
jasonlotito@gmail.com

More Related Content

What's hot

Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
Amazon Web Services
 
Performance testing with 100,000 concurrent users in AWS
Performance testing with 100,000 concurrent users in AWSPerformance testing with 100,000 concurrent users in AWS
Performance testing with 100,000 concurrent users in AWS
Matthias Matook
 
JMeter, Docker sitting in a tree
JMeter, Docker sitting in a treeJMeter, Docker sitting in a tree
JMeter, Docker sitting in a tree
srivaths_sankaran
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
GlobalLogic Ukraine
 
Making sense of your data jug
Making sense of your data   jugMaking sense of your data   jug
Making sense of your data jug
Gerald Muecke
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
Christopher Bartling
 
Performance tests with Gatling (extended)
Performance tests with Gatling (extended)Performance tests with Gatling (extended)
Performance tests with Gatling (extended)
Andrzej Ludwikowski
 
Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express Middleware
Morris Singer
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
Salesforce Developers
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
CRMScienceKirk
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
Knoldus Inc.
 
Painless JavaScript Testing with Jest
Painless JavaScript Testing with JestPainless JavaScript Testing with Jest
Painless JavaScript Testing with Jest
Michał Pierzchała
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
Eric Polerecky
 
Basic testing with selenium
Basic testing with seleniumBasic testing with selenium
Basic testing with selenium
Søren Lund
 
Virtualizing Java in Java (jug.ru)
Virtualizing Java in Java (jug.ru)Virtualizing Java in Java (jug.ru)
Virtualizing Java in Java (jug.ru)
aragozin
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmine
Timothy Oxley
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
Christopher Bartling
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
Gil Fink
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascriptEldar Djafarov
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slides
ericholscher
 

What's hot (20)

Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
Large Scale Load Testing Amazon.com’s Traffic on AWS (CPN102) | AWS re:Invent...
 
Performance testing with 100,000 concurrent users in AWS
Performance testing with 100,000 concurrent users in AWSPerformance testing with 100,000 concurrent users in AWS
Performance testing with 100,000 concurrent users in AWS
 
JMeter, Docker sitting in a tree
JMeter, Docker sitting in a treeJMeter, Docker sitting in a tree
JMeter, Docker sitting in a tree
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
Making sense of your data jug
Making sense of your data   jugMaking sense of your data   jug
Making sense of your data jug
 
JavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and KarmaJavaScript TDD with Jasmine and Karma
JavaScript TDD with Jasmine and Karma
 
Performance tests with Gatling (extended)
Performance tests with Gatling (extended)Performance tests with Gatling (extended)
Performance tests with Gatling (extended)
 
Unit Testing Express Middleware
Unit Testing Express MiddlewareUnit Testing Express Middleware
Unit Testing Express Middleware
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Unit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJSUnit Testing and Coverage for AngularJS
Unit Testing and Coverage for AngularJS
 
Painless JavaScript Testing with Jest
Painless JavaScript Testing with JestPainless JavaScript Testing with Jest
Painless JavaScript Testing with Jest
 
Real world functional reactive programming
Real world functional reactive programmingReal world functional reactive programming
Real world functional reactive programming
 
Basic testing with selenium
Basic testing with seleniumBasic testing with selenium
Basic testing with selenium
 
Virtualizing Java in Java (jug.ru)
Virtualizing Java in Java (jug.ru)Virtualizing Java in Java (jug.ru)
Virtualizing Java in Java (jug.ru)
 
Intro to testing Javascript with jasmine
Intro to testing Javascript with jasmineIntro to testing Javascript with jasmine
Intro to testing Javascript with jasmine
 
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma JavaScript Test-Driven Development with Jasmine 2.0 and Karma
JavaScript Test-Driven Development with Jasmine 2.0 and Karma
 
Quick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmineQuick tour to front end unit testing using jasmine
Quick tour to front end unit testing using jasmine
 
node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slides
 

Viewers also liked

How we killed our process, technology stack, and assumptions – and survived
How we killed our process, technology stack, and assumptions – and survivedHow we killed our process, technology stack, and assumptions – and survived
How we killed our process, technology stack, and assumptions – and survived
Jason Lotito
 
Twitter Bootstrap, or why being a PHP Developer is a bad idea
Twitter Bootstrap, or why being a PHP Developer is a bad ideaTwitter Bootstrap, or why being a PHP Developer is a bad idea
Twitter Bootstrap, or why being a PHP Developer is a bad ideaJason Lotito
 
A Presentation on Presenting
A Presentation on PresentingA Presentation on Presenting
A Presentation on Presenting
Jason Lotito
 
ADHD in Adults
ADHD in AdultsADHD in Adults
ADHD in Adults
Richard Brown
 
Social Media and ADHD – Turning Distractions Into Directions
Social Media and ADHD – Turning Distractions Into DirectionsSocial Media and ADHD – Turning Distractions Into Directions
Social Media and ADHD – Turning Distractions Into Directions
Grant Crowell
 
Getting Things Done - Tips from someone with ADHD and OCD
Getting Things Done - Tips from someone with ADHD and OCDGetting Things Done - Tips from someone with ADHD and OCD
Getting Things Done - Tips from someone with ADHD and OCD
Jason Lotito
 

Viewers also liked (8)

Requirejs
RequirejsRequirejs
Requirejs
 
How we killed our process, technology stack, and assumptions – and survived
How we killed our process, technology stack, and assumptions – and survivedHow we killed our process, technology stack, and assumptions – and survived
How we killed our process, technology stack, and assumptions – and survived
 
Twitter Bootstrap, or why being a PHP Developer is a bad idea
Twitter Bootstrap, or why being a PHP Developer is a bad ideaTwitter Bootstrap, or why being a PHP Developer is a bad idea
Twitter Bootstrap, or why being a PHP Developer is a bad idea
 
Tmux
TmuxTmux
Tmux
 
A Presentation on Presenting
A Presentation on PresentingA Presentation on Presenting
A Presentation on Presenting
 
ADHD in Adults
ADHD in AdultsADHD in Adults
ADHD in Adults
 
Social Media and ADHD – Turning Distractions Into Directions
Social Media and ADHD – Turning Distractions Into DirectionsSocial Media and ADHD – Turning Distractions Into Directions
Social Media and ADHD – Turning Distractions Into Directions
 
Getting Things Done - Tips from someone with ADHD and OCD
Getting Things Done - Tips from someone with ADHD and OCDGetting Things Done - Tips from someone with ADHD and OCD
Getting Things Done - Tips from someone with ADHD and OCD
 

Similar to Load Testing with RedLine13: Or getting paid to DoS your own systems

"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
Fwdays
 
Seven deadly sins of ElasticSearch Benchmarking
Seven deadly sins of ElasticSearch BenchmarkingSeven deadly sins of ElasticSearch Benchmarking
Seven deadly sins of ElasticSearch Benchmarking
Fan Robbin
 
QA Fest 2019. Антон Молдован. Load testing which you always wanted
QA Fest 2019. Антон Молдован. Load testing which you always wantedQA Fest 2019. Антон Молдован. Load testing which you always wanted
QA Fest 2019. Антон Молдован. Load testing which you always wanted
QAFest
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
Fwdays
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
Workhorse Computing
 
Performance testing jmeter
Performance testing jmeterPerformance testing jmeter
Performance testing jmeterBhojan Rajan
 
Performancetestingjmeter 121109061704-phpapp02
Performancetestingjmeter 121109061704-phpapp02Performancetestingjmeter 121109061704-phpapp02
Performancetestingjmeter 121109061704-phpapp02
Shivakumara .
 
Dolphin: Regression Test System for Latitude
Dolphin: Regression Test System for LatitudeDolphin: Regression Test System for Latitude
Dolphin: Regression Test System for Latitude
Tao Jiang
 
Jest: Frontend Testing leicht gemacht @EnterJS2018
Jest: Frontend Testing leicht gemacht @EnterJS2018Jest: Frontend Testing leicht gemacht @EnterJS2018
Jest: Frontend Testing leicht gemacht @EnterJS2018
Holger Grosse-Plankermann
 
Make BDD great again
Make BDD great againMake BDD great again
Make BDD great again
Yana Gusti
 
Load Test Drupal Site Using JMeter and Amazon AWS
Load Test Drupal Site Using JMeter and Amazon AWSLoad Test Drupal Site Using JMeter and Amazon AWS
Load Test Drupal Site Using JMeter and Amazon AWS
Vladimir Ilic
 
Basic Understanding and Implement of Node.js
Basic Understanding and Implement of Node.jsBasic Understanding and Implement of Node.js
Basic Understanding and Implement of Node.js
Gary Yeh
 
Performance Tuning and Optimization
Performance Tuning and OptimizationPerformance Tuning and Optimization
Performance Tuning and Optimization
MongoDB
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
Anton Arhipov
 
PyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web ApplicationsPyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web Applications
Graham Dumpleton
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
Yevgeniy Brikman
 
Practical Chaos Engineering
Practical Chaos EngineeringPractical Chaos Engineering
Practical Chaos Engineering
SIGHUP
 
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
Amazon Web Services
 
Automated acceptance test
Automated acceptance testAutomated acceptance test
Automated acceptance test
Bryan Liu
 

Similar to Load Testing with RedLine13: Or getting paid to DoS your own systems (20)

"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
 
Seven deadly sins of ElasticSearch Benchmarking
Seven deadly sins of ElasticSearch BenchmarkingSeven deadly sins of ElasticSearch Benchmarking
Seven deadly sins of ElasticSearch Benchmarking
 
QA Fest 2019. Антон Молдован. Load testing which you always wanted
QA Fest 2019. Антон Молдован. Load testing which you always wantedQA Fest 2019. Антон Молдован. Load testing which you always wanted
QA Fest 2019. Антон Молдован. Load testing which you always wanted
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
Performance testing jmeter
Performance testing jmeterPerformance testing jmeter
Performance testing jmeter
 
Performancetestingjmeter 121109061704-phpapp02
Performancetestingjmeter 121109061704-phpapp02Performancetestingjmeter 121109061704-phpapp02
Performancetestingjmeter 121109061704-phpapp02
 
Concurrency
ConcurrencyConcurrency
Concurrency
 
Dolphin: Regression Test System for Latitude
Dolphin: Regression Test System for LatitudeDolphin: Regression Test System for Latitude
Dolphin: Regression Test System for Latitude
 
Jest: Frontend Testing leicht gemacht @EnterJS2018
Jest: Frontend Testing leicht gemacht @EnterJS2018Jest: Frontend Testing leicht gemacht @EnterJS2018
Jest: Frontend Testing leicht gemacht @EnterJS2018
 
Make BDD great again
Make BDD great againMake BDD great again
Make BDD great again
 
Load Test Drupal Site Using JMeter and Amazon AWS
Load Test Drupal Site Using JMeter and Amazon AWSLoad Test Drupal Site Using JMeter and Amazon AWS
Load Test Drupal Site Using JMeter and Amazon AWS
 
Basic Understanding and Implement of Node.js
Basic Understanding and Implement of Node.jsBasic Understanding and Implement of Node.js
Basic Understanding and Implement of Node.js
 
Performance Tuning and Optimization
Performance Tuning and OptimizationPerformance Tuning and Optimization
Performance Tuning and Optimization
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
PyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web ApplicationsPyCon AU 2012 - Debugging Live Python Web Applications
PyCon AU 2012 - Debugging Live Python Web Applications
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
 
Practical Chaos Engineering
Practical Chaos EngineeringPractical Chaos Engineering
Practical Chaos Engineering
 
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
(APP307) Leverage the Cloud with a Blue/Green Deployment Architecture | AWS r...
 
Automated acceptance test
Automated acceptance testAutomated acceptance test
Automated acceptance test
 

Recently uploaded

DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 

Recently uploaded (20)

DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 

Load Testing with RedLine13: Or getting paid to DoS your own systems

  • 1. Or getting paid to DoS your own systems Load Testing with RedLine13 Jason Lotito
  • 2. What is Load Testing?
  • 3. Load testing is the process of putting demand on a software system or computing device and measuring its response.
  • 4. Load testing is performed to determine a system's behavior under both normal and anticipated peak load conditions.
  • 5. It helps to identify the maximum operating capacity of an application as well as any bottlenecks and determine which element is causing degradation.
  • 6. What about Stress Testing?
  • 7. Stress testing focuses on throughput. Load testing focuses on response times. Both can be performed at the same time.
  • 8. Load Testing • Putting demand on a system • Measuring the response • Determine behavior under load • Determine maximum operating capacity • Bottlenecks
  • 9. Other Load Testing Tools • ApacheBench (ab) • Apache JMeter • siege • BlazeMeter
  • 10. Why RedLine13? • Simple, up and running in little time • Inexpensive, you pay for what you use • Scriptable, so you have complete control over your tests • I know Rich
  • 11. RedLine13 has a bunch of features you can read about on the website. I’m really here to talk to you about the cool stuff I do with RedLine13.
  • 12. The Basics of Load Testing The Basics of RedLine13 This is another subtitle that I’m apparently supposed to use, in place of the title, and the super subtitle above the title.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 20. Need • Production-level systems to test against • Monitoring • CPU, memory, I/O, etc. • Application dashboards • Logging • Automated systems to deploy • Dedicated people • A time to test
  • 21. Learning • Set goals, e.g. • 50ms • 500rps • Test monitoring • Scaling • What happens to the app under load? • What slows down first?
  • 22. As Load Tester, you are responsible for… • Ensuring those involved with the system under test are aware and available • Putting the system under test under load • Completely destroying the system under load • Providing a clear and concise write up of exactly what occurred • Take charge! It’s fun!
  • 23. Ramp Up Time • Start at what you expect normal traffic to be • 500rps • Start a second test that is just the burst traffic • 900rps • Ramps up over 20 mins • Lasts 40 mins at peak • Ramps down over 20 mins
  • 25. Reporting Results: Shortest Version • 99% @ 59ms
  • 26. Reporting Results: Short Version • Short version: During an hour starting with 0rps to 1400 rps in the first 10 minutes.... • ...when starting with 5 instances and scaling to 11 instances, the response time were: 50% 23ms, 75% 54ms, 95% 303ms, and 99% 1069ms. • ...when starting with 11 instances, the response times were: 50% 16ms, 75% 24ms, 95% 45ms, and 99% 59ms.
  • 27. Reporting Results: Detailed Version • Provide more information • Results • Story driven • Have data supporting results prepared in case • Account for changes such as auto-scaling • With auto-scaling: 99% at 1069ms • Without auto-scaling: 99% at 59ms
  • 28. Testing elasticsearch on c3.4xlarge Detailed Reporting Also included in this report was a link to the actual GitHub repository. Make sure you are keeping your load tests in version control!
  • 29.
  • 30.
  • 31. Tag your load test in git Associate the tag with a Load Test, so you can replay any load test easily
  • 32. PHP & Node.js We’ll be using Node.js for our examples
  • 33. Writing a RedLine13 Custom Load Test in Node.js • Uploading a *.tar.gz/*.zip file • npm install is run • Expects a CustomTest.js file in root directory • CustomTest.js should export a ‘class’ • Will create a new object from • class(redLine, testNum, rand, config) • Will call runTest() on object of class
  • 34. { "name": "reloaded", "version": "1.0.0", "description": "Recommendation Engine Load Tester", "main": "app.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "start": "node app.js", "build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' -- exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *" }, "author": "Jason Lotito <jlotito@meetme.com>", "license": "ISC", "dependencies": { "async": "^1.3.0", "elasticsearch": "^5.0.0", "lodash": "^3.10.0", package.json
  • 35. { "name": "reloaded", "version": "1.0.0", "description": "Recommendation Engine Load Tester", "main": "app.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "start": "node app.js", "build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' -- exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *" }, "author": "Jason Lotito <jlotito@meetme.com>", "license": "ISC", "dependencies": { "async": "^1.3.0", "elasticsearch": "^5.0.0", "lodash": "^3.10.0", package.json
  • 36. { "name": "reloaded", "version": "1.0.0", "description": "Recommendation Engine Load Tester", "main": "app.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "start": "node app.js", "build_test": "rm reloaded.tar.gz && tar --exclude='node_modules' -- exclude='.git' --exclude='logs' -cvzf reloaded.tar.gz *" }, "author": "Jason Lotito <jlotito@meetme.com>", "license": "ISC", "dependencies": { "async": "^1.3.0", "elasticsearch": "^5.0.0", "lodash": "^3.10.0", package.json
  • 37. var Test = require('./CustomTest'); var rl = require('./lib/RedLine'); (new Test(new rl.RedLine, 55)).runTest(function(){ console.log( "test complete"); }); app.js
  • 38. var Test = require('./CustomTest'); var rl = require('./lib/RedLine'); (new Test(new rl.RedLine, 55)).runTest(function(){ console.log( "test complete"); }); app.js
  • 39. var Test = require('./CustomTest'); var rl = require('./lib/RedLine'); (new Test(new rl.RedLine, 55)).runTest(function(){ console.log( "test complete"); }); app.js
  • 40. var Test = require('./CustomTest'); var rl = require('./lib/RedLine'); (new Test(new rl.RedLine, 55)).runTest(function(){ console.log( "test complete"); }); app.js
  • 41. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 42. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 43. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 44. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 45. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 46. function RedLine(){} RedLine.prototype.recordPageTime = function(ts, time){}; RedLine.prototype.recordURLPageLoad = function(url, ts, time){}; RedLine.prototype.recordDownloadSize = function(kb){}; RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } RedLine.js
  • 47. RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } Timer.prototype.start = function () { return new ActiveTimer( Date.now(), this.url, this.redLine ); }; function ActiveTimer( startTime, url, redLineAPI ) { RedLine.js
  • 48. RedLine.prototype.recordError = function(error){console.log(error)}; RedLine.prototype.recordProgress = function(testNum, percent){}; function Timer( url, redLineAPI ) { this.url = url; this.redLine = redLineAPI; } Timer.prototype.start = function () { return new ActiveTimer( Date.now(), this.url, this.redLine ); }; function ActiveTimer( startTime, url, redLineAPI ) { RedLine.js
  • 49. Timer.prototype.start = function () { return new ActiveTimer( Date.now(), this.url, this.redLine ); }; function ActiveTimer( startTime, url, redLineAPI ) { this.endTime = 0; this.startTime = startTime; this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); RedLine.js
  • 50. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 51. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 52. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 53. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 54. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 55. var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, Timer: Timer }; RedLine.js
  • 56. var async = require( 'async' ); var sleep = require( 'sleep' ); var Timer = require( './lib/RedLine' ).Timer; var Test = require( './lib/Test' ); // Load Testing Options var MINUTES_TO_RUN = 60; var MAX_MINUTES_TO_WAIT_BEFORE_START = 10; var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; CustomTest.js
  • 57. var async = require( 'async' ); var sleep = require( 'sleep' ); var Timer = require( './lib/RedLine' ).Timer; var Test = require( './lib/Test' ); // Load Testing Options var MINUTES_TO_RUN = 60; var MAX_MINUTES_TO_WAIT_BEFORE_START = 10; var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; CustomTest.js
  • 58. var sleep = require( 'sleep' ); var Timer = require( './lib/RedLine' ).Timer; var Test = require( './lib/Test' ); // Load Testing Options var MINUTES_TO_RUN = 60; var MAX_MINUTES_TO_WAIT_BEFORE_START = 10; var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; function rand( low, high ) { return Math.floor( Math.random() * (high - low + 1) + low ); } CustomTest.js
  • 59. var sleep = require( 'sleep' ); var Timer = require( './lib/RedLine' ).Timer; var Test = require( './lib/Test' ); // Load Testing Options var MINUTES_TO_RUN = 60; var MAX_MINUTES_TO_WAIT_BEFORE_START = 10; var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; function rand( low, high ) { return Math.floor( Math.random() * (high - low + 1) + low ); } CustomTest.js
  • 60. var sleep = require( 'sleep' ); var Timer = require( './lib/RedLine' ).Timer; var Test = require( './lib/Test' ); // Load Testing Options var MINUTES_TO_RUN = 60; var MAX_MINUTES_TO_WAIT_BEFORE_START = 10; var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; function rand( low, high ) { return Math.floor( Math.random() * (high - low + 1) + low ); } CustomTest.js
  • 61. var MIN_MINUTES_TO_WAIT_BEFORE_START = 0; // Normally don't need to change var RUN_EVERY_MILLISECONDS = 1000; function rand( low, high ) { return Math.floor( Math.random() * (high - low + 1) + low ); } function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; CustomTest.js
  • 62. { return Math.floor( Math.random() * (high - low + 1) + low ); } function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () CustomTest.js
  • 63. { return Math.floor( Math.random() * (high - low + 1) + low ); } function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () CustomTest.js
  • 64. { return Math.floor( Math.random() * (high - low + 1) + low ); } function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () CustomTest.js
  • 65. } function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () { var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60, MAX_MINUTES_TO_WAIT_BEFORE_START * 60 ); CustomTest.js
  • 66. this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () { var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60, MAX_MINUTES_TO_WAIT_BEFORE_START * 60 ); console.log( Date.now() + " - Sleeping for " + sleepInSeconds ); sleep.sleep( sleepInSeconds ); console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); CustomTest.js
  • 67. this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () { var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60, MAX_MINUTES_TO_WAIT_BEFORE_START * 60 ); console.log( Date.now() + " - Sleeping for " + sleepInSeconds ); sleep.sleep( sleepInSeconds ); console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); CustomTest.js
  • 68. this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () { var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60, MAX_MINUTES_TO_WAIT_BEFORE_START * 60 ); console.log( Date.now() + " - Sleeping for " + sleepInSeconds ); sleep.sleep( sleepInSeconds ); console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); CustomTest.js
  • 69. function Reloaded( rl, testNum, rand, config ) { this.rl = rl; this.testNum = testNum; this.rand = rand; this.config = config; this.test = new Test(); this.rampUp(); } Reloaded.prototype.rampUp = function () { var sleepInSeconds = rand( MIN_MINUTES_TO_WAIT_BEFORE_START * 60, MAX_MINUTES_TO_WAIT_BEFORE_START * 60 ); console.log( Date.now() + " - Sleeping for " + sleepInSeconds ); CustomTest.js
  • 70. console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); var max = 60 * MINUTES_TO_RUN; async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { CustomTest.js
  • 71. console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); var max = 60 * MINUTES_TO_RUN; async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { CustomTest.js
  • 72. console.log( Date.now() + " - Done sleeping for " + sleepInSeconds ); }; Reloaded.prototype.runTest = function ( finished ) { var timer = new Timer( 'test', this.rl ); var max = 60 * MINUTES_TO_RUN; async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { CustomTest.js
  • 73. async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () CustomTest.js
  • 74. async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () CustomTest.js
  • 75. async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () CustomTest.js
  • 76. async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () CustomTest.js
  • 77. async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () CustomTest.js
  • 78. var max = 60 * MINUTES_TO_RUN; async.timesSeries( max, function ( n, next ) { var activeTimer = new timer.start(); var timeDiff = 0; this.test.runATest( function ( err ) { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); CustomTest.js
  • 79. { if ( err ) { this.rl.recordError( err.message ); } timeDiff = activeTimer.stop(); setTimeout( next, RUN_EVERY_MILLISECONDS - timeDiff ); }.bind( this ) ); }.bind( this ), function () { finished( true ); } ); }; CustomTest.js
  • 80. Now, let’s hack logging By default,RedLine doesn’t support logging through the web UI
  • 81. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 82. this.redLine = redLineAPI; this.url = url; } ActiveTimer.prototype.stop = function () { this.endTime = Date.now(); var timeDiff = this.endTime - this.startTime; this.redLine.recordError(timeDiff); this.redLine.recordPageTime( this.startTime/1000, timeDiff/1000 ); this.redLine.recordURLPageLoad( this.url, this.startTime/1000, timeDiff/1000 ); return timeDiff; }; module.exports= { RedLine: RedLine, RedLine.js
  • 83.
  • 85.
  • 87. With this we can get percentiles Of course, the pro version offers this for PHP
  • 88.
  • 89.
  • 90.
  • 91. You can use error reporting to simulate real time logging The important thing here is…
  • 93. Things to Keep In Mind • Understand expected usage • X% of users using the app while • Y% are chatting with one another • Users are logging in • Creating accounts • Backend systems • Determine what’s important
  • 94. Things to Keep In Mind • User input • Random filters • Weighted filters • Cached results are expected • Client constraints
  • 95. Things to Keep In Mind • User flow through service • Try to understand how users use the app • Script should try to mimic
  • 96. Things to Keep In Mind • Be care about testing a single system • System will have logging • System will have backend services • You’d be surprised what can cause failure • A Load Test helps you learn before it’s in production
  • 97. Things to Keep In Mind • User interaction • MeetMe is social, so we’ve load tested chatting • 1 test per 2 users, both chatting with one another • Story time!
  • 98. Things to Keep In Mind • Have developers available • Better, have developers with you when load testing • Find a problem, Fix it, Reroll app, Rerun test • FFRR • I just made that up • Don’t use it.
  • 99. Things to Keep In Mind • Start testing from your laptop • Seriously, my MacBook Air could bring down Erlang services • Database indexes are a thing • While running a load test, you can run a single client form your laptop
  • 100. Things to Keep In Mind • Someone should be testing the app/service as well • Response times are only a number • What does 50ms vs 300ms response times feel to the user • What impact does 2x/3x/4x load have • When auto-scaling, how does the client handle
  • 101. Things to Keep In Mind • Review how the client is using the API • Review how the API developer expects the client to use the API • Model after what the client is doing • Call out differences early
  • 103. In Russia, Load tests You! Good load tests will teach you things you didn’t know about your systems. Great load tests will help you solve those problems before they become production problems.
  • 104. Load Testing with RedLine13 Thanks! @jasonlotito jasonlotito.com jasonlotito@gmail.com