Skip to content

Commit

Permalink
Change from wait_time naming from rps to ips (iterations per second) …
Browse files Browse the repository at this point in the history
…because that is what it really is.
  • Loading branch information
cyberw committed Jan 23, 2020
1 parent 20dade2 commit 7cfcbd8
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 29 deletions.
10 changes: 5 additions & 5 deletions locust/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def __init__(self, locust_classes, options):
self.stepload_greenlet = None
self.current_cpu_usage = 0
self.cpu_warning_emitted = False
self.rps_warning_emitted = False
self.ips_warning_emitted = False
self.greenlet.spawn(self.monitor_cpu)
self.exceptions = {}
self.stats = global_stats
Expand Down Expand Up @@ -81,11 +81,11 @@ def cpu_log_warning(self):
logger.warning("Loadgen CPU usage was too high at some point during the test! See https://docs.locust.io/en/stable/running-locust-distributed.html for how to distribute the load over multiple CPU cores or machines")
return self.cpu_warning_emitted

def rps_log_warning(self):
def ips_log_warning(self):
"""Called at the end of the test to repeat the warning & return the status"""
if self.rps_warning_emitted:
logger.warning("Failed to reach target RPS (at some point during the test). The most common cause of this is target system overload or too few clients")
return self.rps_warning_emitted
if self.ips_warning_emitted:
logger.warning("Failed to reach targeted number of iterations per second (at some point during the test). The most common cause of this is target system overload or too few clients")
return self.ips_warning_emitted

def weight_locusts(self, amount):
"""
Expand Down
12 changes: 6 additions & 6 deletions locust/test/test_runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
SlaveLocustRunner, STATE_INIT, STATE_HATCHING, STATE_RUNNING, STATE_MISSING
from locust.stats import global_stats, RequestStats
from locust.test.testcases import LocustTestCase
from locust.wait_time import between, constant, constant_rps_total
from locust.wait_time import between, constant, constant_ips_total


def mocked_rpc():
Expand Down Expand Up @@ -534,8 +534,8 @@ class MyLocust(Locust):
self.assertTrue("HeyAnException" in exception["traceback"])
self.assertEqual(2, exception["count"])

def test_constant_rps_total(self):
target_rps = 50
def test_constant_ips_total(self):
target_ips = 50
run_time = 3

class MyTestLocust(Locust):
Expand All @@ -544,16 +544,16 @@ class task_set(TaskSet):
@task
def the_task(self):
MyTestLocust.i = MyTestLocust.i + 1
wait_time = constant_rps_total(target_rps)
wait_time = constant_ips_total(target_ips)

options = mocked_options()
runner = LocalLocustRunner([MyTestLocust], options)
runners.locust_runner = runner # this is necessary for rps_total
runners.locust_runner = runner # this is necessary for ips_total
runner.start_hatching(10, 999)
gevent.sleep(run_time)
runner.quit()
locust_runner = None # just in case someone depends on this not being set
self.assertAlmostEqual(MyTestLocust.i, target_rps * run_time, delta=25)
self.assertAlmostEqual(MyTestLocust.i, target_ips * run_time, delta=1)

class TestSlaveLocustRunner(LocustTestCase):
def setUp(self):
Expand Down
8 changes: 4 additions & 4 deletions locust/test/test_wait_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from locust.core import HttpLocust, Locust, TaskSet, events, task
from locust.exception import MissingWaitTimeError
from locust.wait_time import between, constant, constant_pacing, constant_rps, constant_rps_total
from locust.wait_time import between, constant, constant_pacing, constant_ips, constant_ips_total

from .testcases import LocustTestCase, WebserverTestCase

Expand Down Expand Up @@ -70,10 +70,10 @@ class TS(TaskSet):
_ = ts2.wait_time()
_ = ts2.wait_time()

def test_constant_rps(self):
# Note: constant_rps_total is tested in test_runners.py, because it requires a runner
def test_constant_ips(self):
# Note: constant_ips_total is tested in test_runners.py, because it requires a runner
class User(Locust):
wait_time = constant_rps(10)
wait_time = constant_ips(10)
class TS(TaskSet):
pass
ts = TS(User())
Expand Down
29 changes: 15 additions & 14 deletions locust/wait_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,47 +61,48 @@ def wait_time_func(self):
return wait_time_func


def constant_rps(rps):
def constant_ips(ips):
"""
This behaves exactly the same as constant_pacing but with an inverted parameter.
It takes requests per second as a parameter instead of time between requests.
It takes iterations per second as a parameter instead of time between iterations.
"""

return constant_pacing(1.0 / rps)
return constant_pacing(1.0 / ips)


def constant_rps_total(rps):
def constant_ips_total(ips):
"""
Returns a function that will track the run time of all tasks in this locust process,
and for each time it's called it will return a wait time that will try to make the
execution equal to the time specified by the wait_time argument.
This is similar to constant_rps, but looks at all clients/locusts in a locust process.
This is similar to constant_ips, but looks at all clients/locusts in a locust process.
Note that in a distributed run, the RPS limit is applied per-slave, not globally.
Note that in a distributed run, the iterations per second limit is applied per-slave, not globally.
During rampup, the RPS is intentionally constrained to be the requested rps * the share of running clients.
During rampup, the IPS is intentionally constrained to be the requested ips * the share of running clients.
Will output a warning if RPS target is missed twice in a row
Will output a warning if IPS target is missed twice in a row
"""

def wait_time_func(self):
lr = runners.locust_runner
if not lr:
logging.warning(
"You asked for constant total rps, but you seem to be running a locust directly. Hopefully you are only running one locust, in which case this will give a somewhat reasonable estimate."
"You asked for constant total ips, but you seem to be running a locust directly. Hopefully you are only running one locust, in which case this will give a somewhat reasonable estimate."
)
return 1.0 / rps
return 1.0 / ips
current_time = float(time())
unstarted_clients = lr.num_clients - len(lr.locusts)
if not hasattr(self, "_cp_last_run"):
print("first run")
self._cp_last_run = 0
self._cp_target_missed = False
next_time = self._cp_last_run + (lr.num_clients + unstarted_clients) / rps
next_time = self._cp_last_run + (lr.num_clients + unstarted_clients) / ips
if current_time > next_time:
if lr.state == runners.STATE_RUNNING and self._cp_target_missed and not lr.rps_warning_emitted:
logging.warning("Failed to reach target rps, even after rampup has finished")
lr.rps_warning_emitted = True # stop logging
if lr.state == runners.STATE_RUNNING and self._cp_target_missed and not lr.ips_warning_emitted:
logging.warning("Failed to reach target ips, even after rampup has finished")
lr.ips_warning_emitted = True # stop logging
self._cp_target_missed = True
self._cp_last_run = current_time
return 0
Expand Down

0 comments on commit 7cfcbd8

Please sign in to comment.