locust 2.30.1.dev20__py3-none-any.whl → 2.30.1.dev25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- locust/_version.py +2 -2
- locust/dispatch.py +27 -48
- {locust-2.30.1.dev20.dist-info → locust-2.30.1.dev25.dist-info}/METADATA +1 -1
- {locust-2.30.1.dev20.dist-info → locust-2.30.1.dev25.dist-info}/RECORD +7 -7
- {locust-2.30.1.dev20.dist-info → locust-2.30.1.dev25.dist-info}/LICENSE +0 -0
- {locust-2.30.1.dev20.dist-info → locust-2.30.1.dev25.dist-info}/WHEEL +0 -0
- {locust-2.30.1.dev20.dist-info → locust-2.30.1.dev25.dist-info}/entry_points.txt +0 -0
locust/_version.py
CHANGED
@@ -14,7 +14,7 @@ __version_tuple__: VERSION_TUPLE
|
|
14
14
|
version_tuple: VERSION_TUPLE
|
15
15
|
|
16
16
|
|
17
|
-
__version__ = "2.30.1.
|
17
|
+
__version__ = "2.30.1.dev25"
|
18
18
|
version = __version__
|
19
|
-
__version_tuple__ = (2, 30, 1, "
|
19
|
+
__version_tuple__ = (2, 30, 1, "dev25")
|
20
20
|
version_tuple = __version_tuple__
|
locust/dispatch.py
CHANGED
@@ -5,7 +5,7 @@ import itertools
|
|
5
5
|
import math
|
6
6
|
import time
|
7
7
|
from collections import defaultdict
|
8
|
-
from collections.abc import
|
8
|
+
from collections.abc import Iterator
|
9
9
|
from heapq import heapify, heapreplace
|
10
10
|
from math import log2
|
11
11
|
from operator import attrgetter
|
@@ -17,41 +17,31 @@ if TYPE_CHECKING:
|
|
17
17
|
from locust import User
|
18
18
|
from locust.runners import WorkerNode
|
19
19
|
|
20
|
+
from collections.abc import Generator, Iterable
|
21
|
+
from typing import TypeVar
|
20
22
|
|
21
|
-
|
22
|
-
# place `@profile` on the functions/methods you wish to profile. Then, in the unit test you are
|
23
|
-
# running, use `from locust.dispatch import profile; profile.print_stats()` at the end of the unit test.
|
24
|
-
# Placing it in a `finally` block is recommended.
|
25
|
-
# import line_profiler
|
26
|
-
#
|
27
|
-
# profile = line_profiler.LineProfiler()
|
23
|
+
T = TypeVar("T")
|
28
24
|
|
29
25
|
|
30
|
-
def _kl_generator(users:
|
26
|
+
def _kl_generator(users: Iterable[tuple[T, float]]) -> Iterator[T | None]:
|
31
27
|
"""Generator based on Kullback-Leibler divergence
|
32
28
|
|
33
29
|
For example, given users A, B with weights 5 and 1 respectively,
|
34
30
|
this algorithm will yield AAABAAAAABAA.
|
35
31
|
"""
|
36
|
-
|
32
|
+
heap = [(x * log2(x / (x + 1.0)), x + 1.0, x, name) for name, x in users]
|
33
|
+
if not heap:
|
37
34
|
while True:
|
38
35
|
yield None
|
39
36
|
|
40
|
-
names = [u[0].__name__ for u in users]
|
41
|
-
weights = [u[1] for u in users]
|
42
|
-
generated = weights.copy()
|
43
|
-
|
44
|
-
heap = [(x * log2(x / (x + 1.0)), i) for i, x in enumerate(generated)]
|
45
37
|
heapify(heap)
|
46
|
-
|
47
38
|
while True:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
kl_diff = weights[i] * log2(x / (x + 1.0))
|
39
|
+
_, x, weight, name = heap[0]
|
40
|
+
# (divergence diff, number of generated elements + initial weight, initial weight, name) = heap[0]
|
41
|
+
yield name
|
42
|
+
kl_diff = weight * log2(x / (x + 1.0))
|
53
43
|
# calculate how much choosing element i for (x + 1)th time decreases divergence
|
54
|
-
heapreplace(heap, (kl_diff,
|
44
|
+
heapreplace(heap, (kl_diff, x + 1.0, weight, name))
|
55
45
|
|
56
46
|
|
57
47
|
class UsersDispatcher(Iterator):
|
@@ -378,35 +368,24 @@ class UsersDispatcher(Iterator):
|
|
378
368
|
return users_on_workers, user_gen, worker_gen, active_users
|
379
369
|
|
380
370
|
def _user_gen(self) -> Iterator[str | None]:
|
381
|
-
|
382
|
-
|
383
|
-
fixed_users_gen = _kl_generator([(u, u.fixed_count) for u in fixed_users.values()])
|
384
|
-
weighted_users_gen = _kl_generator([(u, u.weight) for u in self._user_classes if not u.fixed_count])
|
371
|
+
weighted_users_gen = _kl_generator((u.__name__, u.weight) for u in self._user_classes if not u.fixed_count)
|
385
372
|
|
386
|
-
# Spawn users
|
387
373
|
while True:
|
388
|
-
if self._try_dispatch_fixed:
|
374
|
+
if self._try_dispatch_fixed: # Fixed_count users are spawned before weight users.
|
375
|
+
# Some peoples treat this implementation detail as a feature.
|
389
376
|
self._try_dispatch_fixed = False
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
if self._try_dispatch_fixed:
|
403
|
-
current_fixed_users_count = {u: self._get_user_current_count(u) for u in fixed_users}
|
404
|
-
spawned_classes.clear()
|
405
|
-
self._try_dispatch_fixed = False
|
406
|
-
else:
|
407
|
-
spawned_classes.add(user_name)
|
408
|
-
|
409
|
-
yield next(weighted_users_gen)
|
377
|
+
fixed_users_missing = [
|
378
|
+
(u.__name__, miss)
|
379
|
+
for u in self._user_classes
|
380
|
+
if u.fixed_count and (miss := u.fixed_count - self._get_user_current_count(u.__name__)) > 0
|
381
|
+
]
|
382
|
+
total_miss = sum(miss for _, miss in fixed_users_missing)
|
383
|
+
fixed_users_gen = _kl_generator(fixed_users_missing) # type: ignore[arg-type]
|
384
|
+
# https://mypy.readthedocs.io/en/stable/common_issues.html#variance
|
385
|
+
for _ in range(total_miss):
|
386
|
+
yield next(fixed_users_gen)
|
387
|
+
else:
|
388
|
+
yield next(weighted_users_gen)
|
410
389
|
|
411
390
|
@staticmethod
|
412
391
|
def _fast_users_on_workers_copy(users_on_workers: dict[str, dict[str, int]]) -> dict[str, dict[str, int]]:
|
@@ -1,12 +1,12 @@
|
|
1
1
|
locust/__init__.py,sha256=Jit8eNUrwuMLqavyFvMZr69e61DILq_KB4yT4MciScw,1681
|
2
2
|
locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
|
3
|
-
locust/_version.py,sha256=
|
3
|
+
locust/_version.py,sha256=EqMYTrmsxIMYJN5IEN9IHM5KBdCZPk993n9MLoREiq0,460
|
4
4
|
locust/argument_parser.py,sha256=FMEWKC5OMVzpliRYa6KJvmpMRFvtlJFoVKxyW9_NJuc,29012
|
5
5
|
locust/clients.py,sha256=OHPv6hBAt4gt3HI67yqyT1qrSsF8uMdCwIRu0kIsRWI,19491
|
6
6
|
locust/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
locust/contrib/fasthttp.py,sha256=1hR2WK-3ACGVsU6Fu4Z4KucVzL1LXMLG6k54KeZdt78,28509
|
8
8
|
locust/debug.py,sha256=We6Z9W0btkKSc7PxWmrZx-xMynvOOsKhG6jmDgQin0g,5134
|
9
|
-
locust/dispatch.py,sha256=
|
9
|
+
locust/dispatch.py,sha256=esAp4k8j1zQ8pX2j01UiYUmWS1-9r-XhQvylYyyFeR0,16228
|
10
10
|
locust/env.py,sha256=e5FNcpoftv8G0D86cR1t1cXatumBmCIDA7DbR1JjOSw,13000
|
11
11
|
locust/event.py,sha256=iXEwIYFzra-j1WRldXB9SUibydtD8q8EIKaFPGTTIjk,8729
|
12
12
|
locust/exception.py,sha256=jGgJ32ubuf4pWdlaVOkbh2Y0LlG0_DHi-lv3ib8ppOE,1791
|
@@ -44,8 +44,8 @@ locust/webui/dist/assets/logo-10854faa.png,sha256=EIVPqr6wE_yqguHaqFHIsH0ZACLSrv
|
|
44
44
|
locust/webui/dist/auth.html,sha256=ce6LfxvmqoPALaphEjP-4IxlbJRzdU5zmCCtfEZ943U,501
|
45
45
|
locust/webui/dist/index.html,sha256=G146HDZhCJhL09QlukJKLbKOh9crxXOhY5KEyIqKd8Q,507
|
46
46
|
locust/webui/dist/report.html,sha256=9nqJLjo08fsNYAzCfoOj2XAd4Ijgfyid6wvr5FKLcf0,1453760
|
47
|
-
locust-2.30.1.
|
48
|
-
locust-2.30.1.
|
49
|
-
locust-2.30.1.
|
50
|
-
locust-2.30.1.
|
51
|
-
locust-2.30.1.
|
47
|
+
locust-2.30.1.dev25.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
|
48
|
+
locust-2.30.1.dev25.dist-info/METADATA,sha256=qPGpuud4qkb_1eTi8mTe9gzM47SjgtQiqbJme0zJrZg,7679
|
49
|
+
locust-2.30.1.dev25.dist-info/WHEEL,sha256=HBsDV7Hj4OTiS1GX6ua7iQXUQTB9UHftbBxr7Q8Xm9c,110
|
50
|
+
locust-2.30.1.dev25.dist-info/entry_points.txt,sha256=RhIxlLwU_Ae_WjimS5COUDLagdCh6IOMyLtgaQxNmlM,43
|
51
|
+
locust-2.30.1.dev25.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|