Locust is a python based tool to load test website, REST APIs and else. You define the behavior of the tasks in python. You can read the doc at docs.locust.io.
Installation
Make sure you have libev
and install python dependencies (Work with Python 3.6):
brew install libev
pip install locustio
Or you can use the available docker version.
Create the load test
Create an example load.py
which will contain the locust task:
class LoadTasks(HttpLocust):
host = url
task_set = ExampleTaskSequence
min_wait = 0
max_wait = 1000
Then we can create an ExampleTaskSequence
class with the different requests that will be used
in the load test.
Here let’s use TaskSequence @seq_task(1)
(with the number corresponding of the number in which they are going to be used)
instead of a @task(1)
where the number correspond to the weight of the task.
class ExampleTaskSequence(TaskSequence):
def __init__(self, parent):
super().__init__(parent)
self.token = create_token()
@seq_task(1)
def login(self):
self.client.post(url, data={"payload":"payload"}},
headers=headers, name="login", auth=(username, password), verify=False)
@seq_task(2)
def disconnect (self):
self.client.post(url, verify=False, auth=(username, password), name="disconnect")
To reduce the code size and for the sack of example some function are being called and defined else where.
The name
in the self.client
will be used in the summary in the locust graph instead of the url by default.
It works pretty much like requests
so you can test your http command with it and straight copy / paste it in locust.
Run the Load test
Single instance
Use this command:
# Execute a loadTest
locust -f load.py LoadTask
You can start it with the locust GUI at localhost:8089 The logs are generated in the terminal and there so you can check what is happening.
You can also run it without web interface using:
locust -f load.py LoadTask --no-web --clients=500 --hatch-rate=500
Where you specify:
client
: Total number of simulated customerhatch-rate
: Number of new customer created per seconds until it reachesclient
Distributed
Locust run on one Thread, but you can run it on a distributed way with master and slaves.
Use this command to start the master:
locust -f load.py --master
The you can start as many slave as you CPU can, using:
locust -f load.py --slave --master-host=127.0.0.1
Interpret the Data
In Locust. When you go in charts on the web UI, you’ll see three of them:
- Total requests per second:
- Tracks the number of requests send per second during the load test time
- Response time(ms):
- Median (=50th percentile) in green: It means 50% of the user have a response time inferior or equal to the one said
- 95th percentile in yellow: Represents the real traffic, 95% of your users will be under this response time.
- Number of Users:
- The number of active user created
- It depends on the max number of users created at the start, and the hatch/second rate.
Statistics definitions
Let say we have these 12 response time for 12 requests that have been sent during one second:
rt = [11, 12, 23, 24, 30, 31, 47, 48, 52, 53, 55, 57]
Out of that we can get for that second these statistical data:
- Average: The same as the mean, you take the sum of all response time divided by the number of request
average = sum(rt) / len(rt)
>> 443 / 12 = 36.9
- Median: You take the value that is at half of your ordered data
- For an odd number of data take the middle one (ex: 5, median is the value of the 3rd one - 1, 2,
3
, 4, 5) - For an even number of data take the mean of the middles one (ex: 4 median is the mean of the values of 2nd and 3rd one - 1,
2
,3
, 4)
- For an odd number of data take the middle one (ex: 5, median is the value of the 3rd one - 1, 2,
median = (rt[5] + rt[6]) / 2
>> (31 + 47) / 39
- 95th percentile: The value at 95th percent of the dataset
- For a dataset of 100, the 95th percentile will be the 95th value from the ordered dataset. (…, 93, 94,
95
, 96, 97, 98, 99, 100.)
- For a dataset of 100, the 95th percentile will be the 95th value from the ordered dataset. (…, 93, 94,
percentile = rt[int(round(0.95 * len(rt)) - 1)]
>> rt[10] = 55 # for the 11th element of the list