Skip to content

Commit 742811a

Browse files
committed
update max processes limit
1 parent 0663ef2 commit 742811a

File tree

6 files changed

+65
-37
lines changed

6 files changed

+65
-37
lines changed

docker-compose.dev.yml

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,16 @@ services:
5959
mysql:
6060
condition: service_healthy
6161
environment:
62-
- DB_HOST=mysql
63-
- DB_PORT=3306
64-
- DB_USER=root
65-
- DB_PASSWORD=lmeterx123
66-
- DB_NAME=lmeterx
67-
- DOCKER_CONTAINER=true
68-
- TERM=dumb
69-
- PYTHONUNBUFFERED=1
62+
DB_HOST: mysql
63+
DB_PORT: 3306
64+
DB_USER: root
65+
DB_PASSWORD: lmeterx123
66+
DB_NAME: lmeterx
7067
# Multi-process configuration
71-
- ENABLE_MULTIPROCESS=auto
72-
- LOCUST_CPU_CORES=2.0 # Unified CPU core specification (matches deploy.resources.limits.cpus)
73-
- MULTIPROCESS_THRESHOLD=1000 # Enable multiprocess when users >= 1000
74-
- MIN_USERS_PER_PROCESS=100 # Each process handles at least 100 users
68+
ENABLE_MULTIPROCESS: auto
69+
LOCUST_CPU_CORES: 2.0
70+
MULTIPROCESS_THRESHOLD: 1000
71+
MIN_USERS_PER_PROCESS: 100 # Each process handles at least 100 users
7572
volumes:
7673
- ./logs:/logs
7774
- ./upload_files:/app/upload_files

docker-compose.yml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,16 @@ services:
5353
mysql:
5454
condition: service_healthy
5555
environment:
56-
- DB_HOST=mysql
57-
- DB_PORT=3306
58-
- DB_USER=root
59-
- DB_PASSWORD=lmeterx123
60-
- DB_NAME=lmeterx
61-
- DOCKER_CONTAINER=true
62-
- TERM=dumb
63-
- PYTHONUNBUFFERED=1
56+
DB_HOST: mysql
57+
DB_PORT: 3306
58+
DB_USER: root
59+
DB_PASSWORD: lmeterx123
60+
DB_NAME: lmeterx
6461
# Multi-process configuration
65-
- ENABLE_MULTIPROCESS=auto
66-
- LOCUST_CPU_CORES=2.0 # Unified CPU core specification (matches deploy.resources.limits.cpus)
67-
- MULTIPROCESS_THRESHOLD=1000 # Enable multiprocess when users >= 1000
68-
- MIN_USERS_PER_PROCESS=100 # Each process handles at least 100 users
62+
ENABLE_MULTIPROCESS: auto
63+
LOCUST_CPU_CORES: 2.0
64+
MULTIPROCESS_THRESHOLD: 1000
65+
MIN_USERS_PER_PROCESS: 100
6966
volumes:
7067
- ./logs:/logs
7168
- ./upload_files:/app/upload_files
@@ -75,7 +72,7 @@ services:
7572
deploy:
7673
resources:
7774
limits:
78-
cpus: '2.0' # Must match LOCUST_CPU_CORES
75+
cpus: '2.0'
7976
memory: 2G
8077
reservations:
8178
cpus: '1.0'

st_engine/config/multiprocess.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ def config(self) -> Dict[str, Any]:
2727
"cpu_cores": os.environ.get("LOCUST_CPU_CORES", ""),
2828
"processes": os.environ.get("LOCUST_PROCESSES", ""),
2929
"multiprocess_threshold": int(
30-
os.environ.get("MULTIPROCESS_THRESHOLD", "5")
30+
os.environ.get("MULTIPROCESS_THRESHOLD", "1000")
3131
),
3232
"min_users_per_process": int(
33-
os.environ.get("MIN_USERS_PER_PROCESS", "5")
33+
os.environ.get("MIN_USERS_PER_PROCESS", "100")
3434
),
3535
"force_single_process": os.environ.get(
3636
"FORCE_SINGLE_PROCESS", "false"
@@ -80,7 +80,7 @@ def _detect_cpu_count(self) -> int:
8080

8181
# Respect container limits in Docker environment
8282
if self.is_docker:
83-
return min(system_cpu_count, 8) # Limit to 8 processes for safety
83+
return min(system_cpu_count, 4) # Limit to 4 processes for safety
8484

8585
return system_cpu_count
8686
except (ImportError, NotImplementedError):
@@ -238,12 +238,12 @@ def get_fallback_queue_type() -> str:
238238

239239
# Performance tuning parameters, clearer names
240240
MULTIPROCESS_THRESHOLD = int(
241-
os.environ.get("MULTIPROCESS_THRESHOLD", "5")
241+
os.environ.get("MULTIPROCESS_THRESHOLD", "1000")
242242
) # Min users to enable multiprocess (must be > 1000)
243243

244244
MIN_USERS_PER_PROCESS = int(
245-
os.environ.get("MIN_USERS_PER_PROCESS", "5")
246-
) # Min users each process should handle (updated from 500)
245+
os.environ.get("MIN_USERS_PER_PROCESS", "100")
246+
) # Min users each process should handle
247247

248248

249249
__all__ = [

st_engine/engine/core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class GlobalConfig:
6666
cert_config: Optional[Union[str, Tuple[str, str]]] = None
6767
field_mapping: Optional[str] = None
6868
test_data: Optional[str] = None
69+
duration: int = 60
6970

7071

7172
@dataclass

st_engine/engine/locustfile.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
import sys
1313
import tempfile
1414
import time
15-
from typing import Any, Dict, Optional, Tuple
15+
from dataclasses import field
16+
from typing import Any, Dict, Optional, Tuple, Union
1617

1718
import urllib3
1819
from gevent import queue
@@ -24,6 +25,7 @@
2425

2526
from config.base import (
2627
DEFAULT_API_PATH,
28+
DEFAULT_CONTENT_TYPE,
2729
DEFAULT_PROMPT,
2830
DEFAULT_TIMEOUT,
2931
DEFAULT_WAIT_TIME_MAX,
@@ -218,6 +220,12 @@ def init_parser(parser):
218220
default="",
219221
help="Custom test data in JSONL format or file path",
220222
)
223+
parser.add_argument(
224+
"--duration",
225+
type=int,
226+
default=60,
227+
help="Test duration in seconds (used as fallback when start_time is unavailable)",
228+
)
221229

222230

223231
@events.init.add_listener
@@ -256,6 +264,7 @@ def on_locust_init(environment, **kwargs):
256264
global_config.key_file = options.key_file
257265
global_config.field_mapping = options.field_mapping
258266
global_config.test_data = options.test_data
267+
global_config.duration = int(options.duration)
259268

260269
# Parse and validate configuration
261270
global_config.headers = ConfigManager.parse_headers(
@@ -420,9 +429,35 @@ def on_test_stop(environment, **kwargs):
420429
global_config = get_global_config()
421430
task_id = global_config.task_id
422431
task_logger = GlobalStateManager.get_task_logger(task_id)
432+
433+
execution_time = None
423434
start_time = GlobalStateManager.get_start_time()
424435
end_time = time.time()
425-
execution_time = max(end_time - start_time, 0.001) # avoid division by zero
436+
437+
try:
438+
if start_time is not None and end_time is not None:
439+
execution_time = max(end_time - start_time, 0.001)
440+
else:
441+
duration = getattr(global_config, "duration", None)
442+
if duration is not None and duration > 0:
443+
execution_time = float(duration)
444+
else:
445+
execution_time = 60.0
446+
task_logger.error(
447+
f"Failed to get effective execution time: start_time={start_time}, duration={duration}"
448+
)
449+
450+
raise ValueError(
451+
f"Failed to get effective execution time: start_time={start_time}, duration={duration}"
452+
)
453+
454+
except Exception as e:
455+
task_logger.error(
456+
"Failed to calculate execution time: %s" % str(e), exc_info=True
457+
)
458+
execution_time = 60.0
459+
raise RuntimeError("Failed to calculate execution time: %s" % str(e))
460+
426461
from utils.common import calculate_custom_metrics, get_locust_stats
427462

428463
# Check if this is a worker process
@@ -461,7 +496,8 @@ def on_test_stop(environment, **kwargs):
461496

462497
task_logger.debug(
463498
f"Process type: {'Worker' if is_worker else 'Master'}, "
464-
f"Multi-process: {is_multiprocess}, Worker count: {worker_count}"
499+
f"Multi-process: {is_multiprocess}, Worker count: {worker_count}, "
500+
f"Execution time: {execution_time}"
465501
)
466502

467503
# === WORKER PROCESS LOGIC ===

st_engine/engine/runner.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,6 @@ def read_output(pipe, lines, stream_name):
296296
# This includes the task duration, Locust's own stop timeout, and an extra buffer.
297297
locust_stop_timeout_config = 99
298298
wait_timeout_total = task_duration_seconds + locust_stop_timeout_config + 30
299-
task_logger.info(
300-
f"Waiting for Locust process {process.pid} to complete with a timeout of {wait_timeout_total} seconds."
301-
)
302299

303300
try:
304301
process.wait(timeout=wait_timeout_total)

0 commit comments

Comments
 (0)