Skip to content

Instantly share code, notes, and snippets.

@deanrad
Last active May 3, 2018 18:34
Show Gist options
  • Save deanrad/6284d7b8d634b6f0bb8ae28a063a21a1 to your computer and use it in GitHub Desktop.
Save deanrad/6284d7b8d634b6f0bb8ae28a063a21a1 to your computer and use it in GitHub Desktop.
Load testing with RxJS

rxjstests

This script spins up a number of agents (default 4), each with a certain average timeBetweenActions (default 400msec), and it uses a Poisson process in order to keep that average timeBetweenActions, but randomly distributed within that constraint. Think - popcorn popping!

This statistical trick is a valid model of random arrivals of users at a website, and will distribute load nicely. Thanks to the live-updating progress indicators of ascii-progress, and the awesome stream-fu provided by RxJS!

Here's a short video of my thoughts on the matter: https://www.youtube.com/watch?v=0GnB8FAJjfY

import Rx from 'rxjs'
import ProgressBar from 'ascii-progress'
/* Test config */
const numAgents = 4
const numActionsPerAgent = 12
const timeBetweenActions = 400
const agentOffset = timeBetweenActions / numAgents
/* Run test ! */
let agents = Rx.Observable
.range(0, numAgents)
let work = agents
.map(i => ({
index: i,
progress: new ProgressBar({
schema: ':bar :current/:total :percent :elapseds :etas',
total: numActionsPerAgent,
blank: '◦',
filled: '●'
})
})).mergeMap(({ index, progress }) => {
// every agent gets turned into a stream that
return Rx.Observable.concat(
// begins with an offset delay
Rx.Observable.timer(index * agentOffset),
// then proceeds with #numActionsPerAgent actions
Rx.Observable
.range(0, numActionsPerAgent)
// spaced out by on average timeBetweenActions, but with some jitter
.concatMap(() =>
// add some random jitter around timeBetweenActions
Rx.Observable.timer(-Math.log(1.0 - Math.random()) * timeBetweenActions)
)
// and ticking on each one
.do(() => {
/*
TODO insert real work here (if async, place the tick() inside a then() block)
*/
progress.tick()
})
)
})
work.subscribe({
complete() {
/* Show results and exit */
console.log('Tests pass YAY!')
process.exit(0)
},
error(e) {
console.log(e)
process.exit(1)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment