redis-benchmarks-specification 0.1.274__py3-none-any.whl → 0.1.276__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.
Potentially problematic release.
This version of redis-benchmarks-specification might be problematic. Click here for more details.
- redis_benchmarks_specification/__common__/timeseries.py +28 -6
- redis_benchmarks_specification/__runner__/args.py +43 -1
- redis_benchmarks_specification/__runner__/remote_profiling.py +329 -0
- redis_benchmarks_specification/__runner__/runner.py +603 -67
- redis_benchmarks_specification/test-suites/defaults.yml +3 -0
- redis_benchmarks_specification/test-suites/memtier_benchmark-10Mkeys-string-get-10B-pipeline-100-nokeyprefix.yml +4 -0
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-100B-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-10B-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-10B-psetex-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-10B-setex-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-1KiB-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-4KiB-expire-use-case.yml +2 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-string-get-10B-pipeline-100-nokeyprefix.yml +4 -0
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-string-mixed-50-50-set-get-with-expiration-240B-400_conns.yml +4 -2
- redis_benchmarks_specification/test-suites/memtier_benchmark-1Mkeys-string-set-with-ex-100B-pipeline-10.yml +1 -1
- redis_benchmarks_specification/test-suites/memtier_benchmark-1key-set-1K-elements-sscan-cursor-count-100.yml +1 -1
- redis_benchmarks_specification/test-suites/memtier_benchmark-1key-set-1K-elements-sscan.yml +1 -1
- redis_benchmarks_specification/test-suites/memtier_benchmark-1key-zset-1K-elements-zscan.yml +1 -1
- redis_benchmarks_specification/test-suites/memtier_benchmark-3Mkeys-string-mixed-50-50-with-512B-values-with-expiration-pipeline-10-400_conns.yml +0 -2
- {redis_benchmarks_specification-0.1.274.dist-info → redis_benchmarks_specification-0.1.276.dist-info}/METADATA +1 -1
- {redis_benchmarks_specification-0.1.274.dist-info → redis_benchmarks_specification-0.1.276.dist-info}/RECORD +24 -31
- redis_benchmarks_specification/test-suites/memtier_benchmark-10Mkeys-string-set-update-del-ex-36000-pipeline-10.yml +0 -32
- redis_benchmarks_specification/test-suites/memtier_benchmark-150Mkeys-string-set-ex-20-pipeline-10.yml +0 -30
- redis_benchmarks_specification/test-suites/memtier_benchmark-50Mkeys-string-set-ex-10-with-precondition-pipeline-10.yml +0 -34
- redis_benchmarks_specification/test-suites/memtier_benchmark-50Mkeys-string-set-ex-10years-pipeline-10.yml +0 -30
- redis_benchmarks_specification/test-suites/memtier_benchmark-50Mkeys-string-set-ex-3-pipeline-10.yml +0 -30
- redis_benchmarks_specification/test-suites/memtier_benchmark-50Mkeys-string-set-ex-random-range-pipeline-10.yml +0 -30
- redis_benchmarks_specification/test-suites/memtier_benchmark-50Mkeys-string-set-update-del-ex-120-pipeline-10.yml +0 -32
- redis_benchmarks_specification/test-suites/memtier_benchmark-80Mkeys-string-set-ex-20-precodition-multiclient-pipeline-10.yml +0 -34
- {redis_benchmarks_specification-0.1.274.dist-info → redis_benchmarks_specification-0.1.276.dist-info}/LICENSE +0 -0
- {redis_benchmarks_specification-0.1.274.dist-info → redis_benchmarks_specification-0.1.276.dist-info}/WHEEL +0 -0
- {redis_benchmarks_specification-0.1.274.dist-info → redis_benchmarks_specification-0.1.276.dist-info}/entry_points.txt +0 -0
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
import math
|
|
5
5
|
import os
|
|
6
6
|
import shutil
|
|
7
|
+
import subprocess
|
|
7
8
|
import sys
|
|
8
9
|
import tempfile
|
|
9
10
|
import traceback
|
|
@@ -62,6 +63,84 @@ from redis_benchmarks_specification.__common__.spec import (
|
|
|
62
63
|
extract_client_tools,
|
|
63
64
|
)
|
|
64
65
|
from redis_benchmarks_specification.__runner__.args import create_client_runner_args
|
|
66
|
+
from redis_benchmarks_specification.__runner__.remote_profiling import RemoteProfiler
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def run_local_command_with_timeout(command_str, timeout_seconds, description="command"):
|
|
70
|
+
"""
|
|
71
|
+
Run a local command with timeout support.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
command_str: The command string to execute
|
|
75
|
+
timeout_seconds: Timeout in seconds
|
|
76
|
+
description: Description for logging
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
tuple: (success, stdout, stderr)
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
logging.info(f"Running {description} with {timeout_seconds}s timeout: {command_str}")
|
|
83
|
+
|
|
84
|
+
# Use shell=True to support complex command strings with pipes, etc.
|
|
85
|
+
process = subprocess.Popen(
|
|
86
|
+
command_str,
|
|
87
|
+
shell=True,
|
|
88
|
+
stdout=subprocess.PIPE,
|
|
89
|
+
stderr=subprocess.PIPE,
|
|
90
|
+
text=True
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
stdout, stderr = process.communicate(timeout=timeout_seconds)
|
|
95
|
+
return_code = process.returncode
|
|
96
|
+
|
|
97
|
+
if return_code == 0:
|
|
98
|
+
logging.info(f"{description} completed successfully")
|
|
99
|
+
return True, stdout, stderr
|
|
100
|
+
else:
|
|
101
|
+
logging.error(f"{description} failed with return code {return_code}")
|
|
102
|
+
logging.error(f"stderr: {stderr}")
|
|
103
|
+
return False, stdout, stderr
|
|
104
|
+
|
|
105
|
+
except subprocess.TimeoutExpired:
|
|
106
|
+
logging.error(f"{description} timed out after {timeout_seconds} seconds")
|
|
107
|
+
process.kill()
|
|
108
|
+
try:
|
|
109
|
+
stdout, stderr = process.communicate(timeout=5) # Give 5 seconds to cleanup
|
|
110
|
+
except subprocess.TimeoutExpired:
|
|
111
|
+
stdout, stderr = "", "Process killed due to timeout"
|
|
112
|
+
return False, stdout, f"Timeout after {timeout_seconds} seconds. {stderr}"
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logging.error(f"Error running {description}: {e}")
|
|
116
|
+
return False, "", str(e)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def calculate_process_timeout(command_str, buffer_timeout):
|
|
120
|
+
"""
|
|
121
|
+
Calculate timeout for a process based on test-time parameter and buffer.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
command_str: The command string to analyze
|
|
125
|
+
buffer_timeout: Buffer time to add to test-time
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
int: Timeout in seconds
|
|
129
|
+
"""
|
|
130
|
+
default_timeout = 300 # 5 minutes default
|
|
131
|
+
|
|
132
|
+
if "test-time" in command_str:
|
|
133
|
+
# Try to extract test time and add buffer
|
|
134
|
+
# Handle both --test-time (memtier) and -test-time (pubsub-sub-bench)
|
|
135
|
+
test_time_match = re.search(r"--?test-time[=\s]+(\d+)", command_str)
|
|
136
|
+
if test_time_match:
|
|
137
|
+
test_time = int(test_time_match.group(1))
|
|
138
|
+
timeout = test_time + buffer_timeout
|
|
139
|
+
logging.info(f"Set process timeout to {timeout}s (test-time: {test_time}s + {buffer_timeout}s buffer)")
|
|
140
|
+
return timeout
|
|
141
|
+
|
|
142
|
+
logging.info(f"Using default process timeout: {default_timeout}s")
|
|
143
|
+
return default_timeout
|
|
65
144
|
|
|
66
145
|
|
|
67
146
|
def parse_size(size):
|
|
@@ -91,6 +170,31 @@ def parse_size(size):
|
|
|
91
170
|
return int(number * units[unit])
|
|
92
171
|
|
|
93
172
|
|
|
173
|
+
def extract_expected_benchmark_duration(benchmark_command_str, override_memtier_test_time):
|
|
174
|
+
"""
|
|
175
|
+
Extract expected benchmark duration from command string or override.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
benchmark_command_str: The benchmark command string
|
|
179
|
+
override_memtier_test_time: Override test time value
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Expected duration in seconds, or 30 as default
|
|
183
|
+
"""
|
|
184
|
+
if override_memtier_test_time > 0:
|
|
185
|
+
return override_memtier_test_time
|
|
186
|
+
|
|
187
|
+
# Try to extract test-time from command string
|
|
188
|
+
if "test-time" in benchmark_command_str:
|
|
189
|
+
# Handle both --test-time (memtier) and -test-time (pubsub-sub-bench)
|
|
190
|
+
test_time_match = re.search(r"--?test-time[=\s]+(\d+)", benchmark_command_str)
|
|
191
|
+
if test_time_match:
|
|
192
|
+
return int(test_time_match.group(1))
|
|
193
|
+
|
|
194
|
+
# Default duration if not found
|
|
195
|
+
return 30
|
|
196
|
+
|
|
197
|
+
|
|
94
198
|
def run_multiple_clients(
|
|
95
199
|
benchmark_config,
|
|
96
200
|
docker_client,
|
|
@@ -181,6 +285,30 @@ def run_multiple_clients(
|
|
|
181
285
|
unix_socket,
|
|
182
286
|
None, # username
|
|
183
287
|
)
|
|
288
|
+
elif "vector-db-benchmark" in client_tool:
|
|
289
|
+
(
|
|
290
|
+
_,
|
|
291
|
+
benchmark_command_str,
|
|
292
|
+
arbitrary_command,
|
|
293
|
+
client_env_vars,
|
|
294
|
+
) = prepare_vector_db_benchmark_parameters(
|
|
295
|
+
client_config,
|
|
296
|
+
client_tool,
|
|
297
|
+
port,
|
|
298
|
+
host,
|
|
299
|
+
password,
|
|
300
|
+
local_benchmark_output_filename,
|
|
301
|
+
oss_cluster_api_enabled,
|
|
302
|
+
tls_enabled,
|
|
303
|
+
tls_skip_verify,
|
|
304
|
+
test_tls_cert,
|
|
305
|
+
test_tls_key,
|
|
306
|
+
test_tls_cacert,
|
|
307
|
+
resp_version,
|
|
308
|
+
override_memtier_test_time,
|
|
309
|
+
unix_socket,
|
|
310
|
+
None, # username
|
|
311
|
+
)
|
|
184
312
|
else:
|
|
185
313
|
# Handle other benchmark tools
|
|
186
314
|
(
|
|
@@ -199,9 +327,8 @@ def run_multiple_clients(
|
|
|
199
327
|
|
|
200
328
|
# Calculate container timeout
|
|
201
329
|
container_timeout = 300 # 5 minutes default
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
) # Configurable buffer from command line
|
|
330
|
+
# Use new timeout_buffer argument, fallback to container_timeout_buffer for backward compatibility
|
|
331
|
+
buffer_timeout = getattr(args, 'timeout_buffer', getattr(args, 'container_timeout_buffer', 60))
|
|
205
332
|
if "test-time" in benchmark_command_str:
|
|
206
333
|
# Try to extract test time and add buffer
|
|
207
334
|
import re
|
|
@@ -224,23 +351,51 @@ def run_multiple_clients(
|
|
|
224
351
|
# Start container (detached)
|
|
225
352
|
import os
|
|
226
353
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
354
|
+
# Set working directory based on tool
|
|
355
|
+
working_dir = benchmark_tool_workdir
|
|
356
|
+
if "vector-db-benchmark" in client_tool:
|
|
357
|
+
working_dir = "/app" # vector-db-benchmark needs to run from /app
|
|
358
|
+
|
|
359
|
+
# Prepare container arguments
|
|
360
|
+
volumes = {
|
|
361
|
+
temporary_dir_client: {
|
|
362
|
+
"bind": client_mnt_point,
|
|
363
|
+
"mode": "rw",
|
|
234
364
|
},
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
# For vector-db-benchmark, also mount the results directory
|
|
368
|
+
if "vector-db-benchmark" in client_tool:
|
|
369
|
+
volumes[temporary_dir_client] = {
|
|
370
|
+
"bind": "/app/results",
|
|
371
|
+
"mode": "rw",
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
container_kwargs = {
|
|
375
|
+
"image": client_image,
|
|
376
|
+
"volumes": volumes,
|
|
377
|
+
"auto_remove": False,
|
|
378
|
+
"privileged": True,
|
|
379
|
+
"working_dir": working_dir,
|
|
380
|
+
"command": benchmark_command_str,
|
|
381
|
+
"network_mode": "host",
|
|
382
|
+
"detach": True,
|
|
383
|
+
"cpuset_cpus": client_cpuset_cpus,
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
# Only add user for non-vector-db-benchmark tools to avoid permission issues
|
|
387
|
+
if "vector-db-benchmark" not in client_tool:
|
|
388
|
+
container_kwargs["user"] = f"{os.getuid()}:{os.getgid()}"
|
|
389
|
+
|
|
390
|
+
# Add environment variables for vector-db-benchmark
|
|
391
|
+
if "vector-db-benchmark" in client_tool:
|
|
392
|
+
try:
|
|
393
|
+
container_kwargs["environment"] = client_env_vars
|
|
394
|
+
except NameError:
|
|
395
|
+
# client_env_vars not defined, skip environment variables
|
|
396
|
+
pass
|
|
397
|
+
|
|
398
|
+
container = docker_client.containers.run(**container_kwargs)
|
|
244
399
|
|
|
245
400
|
containers.append(
|
|
246
401
|
{
|
|
@@ -334,6 +489,7 @@ def run_multiple_clients(
|
|
|
334
489
|
aggregated_json = {}
|
|
335
490
|
memtier_json = None
|
|
336
491
|
pubsub_json = None
|
|
492
|
+
vector_json = None
|
|
337
493
|
|
|
338
494
|
for result in successful_results:
|
|
339
495
|
client_index = result["client_index"]
|
|
@@ -360,6 +516,19 @@ def run_multiple_clients(
|
|
|
360
516
|
logging.info(
|
|
361
517
|
f"Successfully read pubsub-sub-bench JSON output from client {client_index}"
|
|
362
518
|
)
|
|
519
|
+
elif "vector-db-benchmark" in tool:
|
|
520
|
+
# For vector-db-benchmark, look for summary JSON file
|
|
521
|
+
summary_files = [f for f in os.listdir(temporary_dir_client) if f.endswith("-summary.json")]
|
|
522
|
+
if summary_files:
|
|
523
|
+
summary_filepath = os.path.join(temporary_dir_client, summary_files[0])
|
|
524
|
+
try:
|
|
525
|
+
with open(summary_filepath, 'r') as f:
|
|
526
|
+
vector_json = json.load(f)
|
|
527
|
+
logging.info(f"Successfully read vector-db-benchmark JSON output from {summary_files[0]}")
|
|
528
|
+
except Exception as e:
|
|
529
|
+
logging.warning(f"Failed to read vector-db-benchmark JSON from {summary_files[0]}: {e}")
|
|
530
|
+
else:
|
|
531
|
+
logging.warning(f"No vector-db-benchmark summary JSON file found for client {client_index}")
|
|
363
532
|
|
|
364
533
|
logging.info(
|
|
365
534
|
f"Successfully read JSON output from client {client_index} ({tool})"
|
|
@@ -376,16 +545,32 @@ def run_multiple_clients(
|
|
|
376
545
|
f"JSON output file not found for client {client_index}: {json_filepath}"
|
|
377
546
|
)
|
|
378
547
|
|
|
379
|
-
# Merge JSON outputs from
|
|
380
|
-
if memtier_json and pubsub_json:
|
|
548
|
+
# Merge JSON outputs from all tools
|
|
549
|
+
if memtier_json and pubsub_json and vector_json:
|
|
550
|
+
# Use memtier as base and add other metrics
|
|
551
|
+
aggregated_json = memtier_json.copy()
|
|
552
|
+
aggregated_json.update(pubsub_json)
|
|
553
|
+
aggregated_json.update(vector_json)
|
|
554
|
+
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
555
|
+
logging.info("Using merged JSON results from memtier, pubsub-sub-bench, and vector-db-benchmark clients")
|
|
556
|
+
elif memtier_json and pubsub_json:
|
|
381
557
|
# Use memtier as base and add pubsub metrics
|
|
382
558
|
aggregated_json = memtier_json.copy()
|
|
383
|
-
# Add pubsub metrics to the aggregated result
|
|
384
559
|
aggregated_json.update(pubsub_json)
|
|
385
560
|
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
386
|
-
logging.info(
|
|
387
|
-
|
|
388
|
-
|
|
561
|
+
logging.info("Using merged JSON results from memtier and pubsub-sub-bench clients")
|
|
562
|
+
elif memtier_json and vector_json:
|
|
563
|
+
# Use memtier as base and add vector metrics
|
|
564
|
+
aggregated_json = memtier_json.copy()
|
|
565
|
+
aggregated_json.update(vector_json)
|
|
566
|
+
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
567
|
+
logging.info("Using merged JSON results from memtier and vector-db-benchmark clients")
|
|
568
|
+
elif pubsub_json and vector_json:
|
|
569
|
+
# Use pubsub as base and add vector metrics
|
|
570
|
+
aggregated_json = pubsub_json.copy()
|
|
571
|
+
aggregated_json.update(vector_json)
|
|
572
|
+
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
573
|
+
logging.info("Using merged JSON results from pubsub-sub-bench and vector-db-benchmark clients")
|
|
389
574
|
elif memtier_json:
|
|
390
575
|
# Only memtier available
|
|
391
576
|
aggregated_json = memtier_json
|
|
@@ -396,12 +581,15 @@ def run_multiple_clients(
|
|
|
396
581
|
aggregated_json = pubsub_json
|
|
397
582
|
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
398
583
|
logging.info("Using JSON results from pubsub-sub-bench client only")
|
|
584
|
+
elif vector_json:
|
|
585
|
+
# Only vector-db-benchmark available
|
|
586
|
+
aggregated_json = vector_json
|
|
587
|
+
aggregated_stdout = json.dumps(aggregated_json, indent=2)
|
|
588
|
+
logging.info("Using JSON results from vector-db-benchmark client only")
|
|
399
589
|
else:
|
|
400
590
|
# Fall back to concatenated stdout
|
|
401
591
|
aggregated_stdout = "\n".join([r["stdout"] for r in successful_results])
|
|
402
|
-
logging.warning(
|
|
403
|
-
"No JSON results found, falling back to concatenated stdout"
|
|
404
|
-
)
|
|
592
|
+
logging.warning("No JSON results found, falling back to concatenated stdout")
|
|
405
593
|
|
|
406
594
|
return aggregated_stdout, results
|
|
407
595
|
|
|
@@ -665,6 +853,71 @@ def prepare_memtier_benchmark_parameters(
|
|
|
665
853
|
return None, benchmark_command_str, arbitrary_command
|
|
666
854
|
|
|
667
855
|
|
|
856
|
+
def prepare_vector_db_benchmark_parameters(
|
|
857
|
+
clientconfig,
|
|
858
|
+
full_benchmark_path,
|
|
859
|
+
port,
|
|
860
|
+
server,
|
|
861
|
+
password,
|
|
862
|
+
local_benchmark_output_filename,
|
|
863
|
+
oss_cluster_api_enabled=False,
|
|
864
|
+
tls_enabled=False,
|
|
865
|
+
tls_skip_verify=False,
|
|
866
|
+
tls_cert=None,
|
|
867
|
+
tls_key=None,
|
|
868
|
+
tls_cacert=None,
|
|
869
|
+
resp_version=None,
|
|
870
|
+
override_test_time=0,
|
|
871
|
+
unix_socket="",
|
|
872
|
+
username=None,
|
|
873
|
+
):
|
|
874
|
+
"""
|
|
875
|
+
Prepare vector-db-benchmark command parameters
|
|
876
|
+
"""
|
|
877
|
+
arbitrary_command = False
|
|
878
|
+
|
|
879
|
+
benchmark_command = [
|
|
880
|
+
"/app/run.py",
|
|
881
|
+
"--host",
|
|
882
|
+
f"{server}",
|
|
883
|
+
]
|
|
884
|
+
|
|
885
|
+
# Add port as environment variable (vector-db-benchmark uses env vars)
|
|
886
|
+
env_vars = {}
|
|
887
|
+
if port is not None:
|
|
888
|
+
env_vars["REDIS_PORT"] = str(port)
|
|
889
|
+
if password is not None:
|
|
890
|
+
env_vars["REDIS_AUTH"] = password
|
|
891
|
+
if username is not None:
|
|
892
|
+
env_vars["REDIS_USER"] = username
|
|
893
|
+
|
|
894
|
+
# Add engines parameter
|
|
895
|
+
engines = clientconfig.get("engines", "vectorsets-fp32-default")
|
|
896
|
+
benchmark_command.extend(["--engines", engines])
|
|
897
|
+
|
|
898
|
+
# Add datasets parameter
|
|
899
|
+
datasets = clientconfig.get("datasets", "random-100")
|
|
900
|
+
benchmark_command.extend(["--datasets", datasets])
|
|
901
|
+
|
|
902
|
+
# Add other optional parameters
|
|
903
|
+
if "parallels" in clientconfig:
|
|
904
|
+
benchmark_command.extend(["--parallels", str(clientconfig["parallels"])])
|
|
905
|
+
|
|
906
|
+
if "queries" in clientconfig:
|
|
907
|
+
benchmark_command.extend(["--queries", str(clientconfig["queries"])])
|
|
908
|
+
|
|
909
|
+
if "timeout" in clientconfig:
|
|
910
|
+
benchmark_command.extend(["--timeout", str(clientconfig["timeout"])])
|
|
911
|
+
|
|
912
|
+
# Add custom arguments if specified
|
|
913
|
+
if "arguments" in clientconfig:
|
|
914
|
+
benchmark_command_str = " ".join(benchmark_command) + " " + clientconfig["arguments"]
|
|
915
|
+
else:
|
|
916
|
+
benchmark_command_str = " ".join(benchmark_command)
|
|
917
|
+
|
|
918
|
+
return benchmark_command, benchmark_command_str, arbitrary_command, env_vars
|
|
919
|
+
|
|
920
|
+
|
|
668
921
|
def prepare_pubsub_sub_bench_parameters(
|
|
669
922
|
clientconfig,
|
|
670
923
|
full_benchmark_path,
|
|
@@ -899,6 +1152,23 @@ def process_self_contained_coordinator_stream(
|
|
|
899
1152
|
redis_pid = conn.info()["process_id"]
|
|
900
1153
|
redis_pids.append(redis_pid)
|
|
901
1154
|
|
|
1155
|
+
# Check if all tested commands are supported by this Redis instance
|
|
1156
|
+
supported_commands = get_supported_redis_commands(redis_conns)
|
|
1157
|
+
commands_supported, unsupported_commands = check_test_command_support(
|
|
1158
|
+
benchmark_config, supported_commands
|
|
1159
|
+
)
|
|
1160
|
+
|
|
1161
|
+
if not commands_supported:
|
|
1162
|
+
logging.warning(
|
|
1163
|
+
f"Skipping test {test_name} due to unsupported commands: {unsupported_commands}"
|
|
1164
|
+
)
|
|
1165
|
+
delete_temporary_files(
|
|
1166
|
+
temporary_dir_client=temporary_dir_client,
|
|
1167
|
+
full_result_path=None,
|
|
1168
|
+
benchmark_tool_global=benchmark_tool_global,
|
|
1169
|
+
)
|
|
1170
|
+
continue
|
|
1171
|
+
|
|
902
1172
|
github_actor = f"{tf_triggering_env}-{running_platform}"
|
|
903
1173
|
dso = "redis-server"
|
|
904
1174
|
profilers_artifacts_matrix = []
|
|
@@ -1047,6 +1317,9 @@ def process_self_contained_coordinator_stream(
|
|
|
1047
1317
|
continue
|
|
1048
1318
|
if "dbconfig" in benchmark_config:
|
|
1049
1319
|
if "preload_tool" in benchmark_config["dbconfig"]:
|
|
1320
|
+
# Get timeout buffer for preload
|
|
1321
|
+
buffer_timeout = getattr(args, 'timeout_buffer', getattr(args, 'container_timeout_buffer', 60))
|
|
1322
|
+
|
|
1050
1323
|
res = data_prepopulation_step(
|
|
1051
1324
|
benchmark_config,
|
|
1052
1325
|
benchmark_tool_workdir,
|
|
@@ -1067,6 +1340,7 @@ def process_self_contained_coordinator_stream(
|
|
|
1067
1340
|
password,
|
|
1068
1341
|
oss_cluster_api_enabled,
|
|
1069
1342
|
unix_socket,
|
|
1343
|
+
buffer_timeout,
|
|
1070
1344
|
)
|
|
1071
1345
|
if res is False:
|
|
1072
1346
|
logging.warning(
|
|
@@ -1208,6 +1482,30 @@ def process_self_contained_coordinator_stream(
|
|
|
1208
1482
|
unix_socket,
|
|
1209
1483
|
None, # username
|
|
1210
1484
|
)
|
|
1485
|
+
elif "vector-db-benchmark" in benchmark_tool:
|
|
1486
|
+
(
|
|
1487
|
+
_,
|
|
1488
|
+
benchmark_command_str,
|
|
1489
|
+
arbitrary_command,
|
|
1490
|
+
env_vars,
|
|
1491
|
+
) = prepare_vector_db_benchmark_parameters(
|
|
1492
|
+
benchmark_config["clientconfig"],
|
|
1493
|
+
full_benchmark_path,
|
|
1494
|
+
port,
|
|
1495
|
+
host,
|
|
1496
|
+
password,
|
|
1497
|
+
local_benchmark_output_filename,
|
|
1498
|
+
oss_cluster_api_enabled,
|
|
1499
|
+
tls_enabled,
|
|
1500
|
+
tls_skip_verify,
|
|
1501
|
+
test_tls_cert,
|
|
1502
|
+
test_tls_key,
|
|
1503
|
+
test_tls_cacert,
|
|
1504
|
+
resp_version,
|
|
1505
|
+
override_memtier_test_time,
|
|
1506
|
+
unix_socket,
|
|
1507
|
+
None, # username
|
|
1508
|
+
)
|
|
1211
1509
|
else:
|
|
1212
1510
|
# prepare the benchmark command for other tools
|
|
1213
1511
|
(
|
|
@@ -1241,6 +1539,40 @@ def process_self_contained_coordinator_stream(
|
|
|
1241
1539
|
profiler_call_graph_mode,
|
|
1242
1540
|
)
|
|
1243
1541
|
|
|
1542
|
+
# start remote profiling if enabled
|
|
1543
|
+
remote_profiler = None
|
|
1544
|
+
if args.enable_remote_profiling:
|
|
1545
|
+
try:
|
|
1546
|
+
remote_profiler = RemoteProfiler(
|
|
1547
|
+
args.remote_profile_host,
|
|
1548
|
+
args.remote_profile_port,
|
|
1549
|
+
args.remote_profile_output_dir,
|
|
1550
|
+
args.remote_profile_username,
|
|
1551
|
+
args.remote_profile_password
|
|
1552
|
+
)
|
|
1553
|
+
|
|
1554
|
+
# Extract expected benchmark duration
|
|
1555
|
+
expected_duration = extract_expected_benchmark_duration(
|
|
1556
|
+
benchmark_command_str, override_memtier_test_time
|
|
1557
|
+
)
|
|
1558
|
+
|
|
1559
|
+
# Start remote profiling
|
|
1560
|
+
profiling_started = remote_profiler.start_profiling(
|
|
1561
|
+
redis_conns[0] if redis_conns else None,
|
|
1562
|
+
test_name,
|
|
1563
|
+
expected_duration
|
|
1564
|
+
)
|
|
1565
|
+
|
|
1566
|
+
if profiling_started:
|
|
1567
|
+
logging.info(f"Started remote profiling for test: {test_name}")
|
|
1568
|
+
else:
|
|
1569
|
+
logging.warning(f"Failed to start remote profiling for test: {test_name}")
|
|
1570
|
+
remote_profiler = None
|
|
1571
|
+
|
|
1572
|
+
except Exception as e:
|
|
1573
|
+
logging.error(f"Error starting remote profiling: {e}")
|
|
1574
|
+
remote_profiler = None
|
|
1575
|
+
|
|
1244
1576
|
# run the benchmark
|
|
1245
1577
|
benchmark_start_time = datetime.datetime.now()
|
|
1246
1578
|
|
|
@@ -1284,13 +1616,23 @@ def process_self_contained_coordinator_stream(
|
|
|
1284
1616
|
+ " "
|
|
1285
1617
|
+ benchmark_command_str
|
|
1286
1618
|
)
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1619
|
+
|
|
1620
|
+
# Calculate timeout for local process
|
|
1621
|
+
buffer_timeout = getattr(args, 'timeout_buffer', getattr(args, 'container_timeout_buffer', 60))
|
|
1622
|
+
process_timeout = calculate_process_timeout(benchmark_command_str, buffer_timeout)
|
|
1623
|
+
|
|
1624
|
+
# Run with timeout
|
|
1625
|
+
success, client_container_stdout, stderr = run_local_command_with_timeout(
|
|
1626
|
+
benchmark_command_str,
|
|
1627
|
+
process_timeout,
|
|
1628
|
+
"memtier benchmark"
|
|
1291
1629
|
)
|
|
1292
|
-
|
|
1293
|
-
|
|
1630
|
+
|
|
1631
|
+
if not success:
|
|
1632
|
+
logging.error(f"Memtier benchmark failed: {stderr}")
|
|
1633
|
+
# Continue with the test but log the failure
|
|
1634
|
+
client_container_stdout = f"ERROR: {stderr}"
|
|
1635
|
+
|
|
1294
1636
|
move_command = "mv {} {}".format(
|
|
1295
1637
|
local_benchmark_output_filename, temporary_dir_client
|
|
1296
1638
|
)
|
|
@@ -1305,22 +1647,53 @@ def process_self_contained_coordinator_stream(
|
|
|
1305
1647
|
)
|
|
1306
1648
|
|
|
1307
1649
|
# Use explicit container management for single client
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1650
|
+
import os
|
|
1651
|
+
|
|
1652
|
+
# Set working directory based on tool
|
|
1653
|
+
working_dir = benchmark_tool_workdir
|
|
1654
|
+
if "vector-db-benchmark" in benchmark_tool:
|
|
1655
|
+
working_dir = "/app" # vector-db-benchmark needs to run from /app
|
|
1656
|
+
|
|
1657
|
+
# Prepare volumes
|
|
1658
|
+
volumes = {
|
|
1659
|
+
temporary_dir_client: {
|
|
1660
|
+
"bind": client_mnt_point,
|
|
1661
|
+
"mode": "rw",
|
|
1315
1662
|
},
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
# For vector-db-benchmark, also mount the results directory
|
|
1666
|
+
if "vector-db-benchmark" in benchmark_tool:
|
|
1667
|
+
volumes[temporary_dir_client] = {
|
|
1668
|
+
"bind": "/app/results",
|
|
1669
|
+
"mode": "rw",
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
container_kwargs = {
|
|
1673
|
+
"image": client_container_image,
|
|
1674
|
+
"volumes": volumes,
|
|
1675
|
+
"auto_remove": False,
|
|
1676
|
+
"privileged": True,
|
|
1677
|
+
"working_dir": working_dir,
|
|
1678
|
+
"command": benchmark_command_str,
|
|
1679
|
+
"network_mode": "host",
|
|
1680
|
+
"detach": True,
|
|
1681
|
+
"cpuset_cpus": client_cpuset_cpus,
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
# Only add user for non-vector-db-benchmark tools to avoid permission issues
|
|
1685
|
+
if "vector-db-benchmark" not in benchmark_tool:
|
|
1686
|
+
container_kwargs["user"] = f"{os.getuid()}:{os.getgid()}"
|
|
1687
|
+
|
|
1688
|
+
# Add environment variables for vector-db-benchmark
|
|
1689
|
+
if "vector-db-benchmark" in benchmark_tool:
|
|
1690
|
+
try:
|
|
1691
|
+
container_kwargs["environment"] = env_vars
|
|
1692
|
+
except NameError:
|
|
1693
|
+
# env_vars not defined, skip environment variables
|
|
1694
|
+
pass
|
|
1695
|
+
|
|
1696
|
+
container = docker_client.containers.run(**container_kwargs)
|
|
1324
1697
|
|
|
1325
1698
|
# Wait for container and get output
|
|
1326
1699
|
try:
|
|
@@ -1370,7 +1743,25 @@ def process_self_contained_coordinator_stream(
|
|
|
1370
1743
|
test_name,
|
|
1371
1744
|
)
|
|
1372
1745
|
|
|
1746
|
+
# wait for remote profiling completion
|
|
1747
|
+
if remote_profiler is not None:
|
|
1748
|
+
try:
|
|
1749
|
+
logging.info("Waiting for remote profiling to complete...")
|
|
1750
|
+
profiling_success = remote_profiler.wait_for_completion(timeout=60)
|
|
1751
|
+
if profiling_success:
|
|
1752
|
+
logging.info("Remote profiling completed successfully")
|
|
1753
|
+
else:
|
|
1754
|
+
logging.warning("Remote profiling did not complete successfully")
|
|
1755
|
+
except Exception as e:
|
|
1756
|
+
logging.error(f"Error waiting for remote profiling completion: {e}")
|
|
1757
|
+
|
|
1373
1758
|
logging.info("Printing client tool stdout output")
|
|
1759
|
+
if client_container_stdout:
|
|
1760
|
+
print("=== Container Output ===")
|
|
1761
|
+
print(client_container_stdout)
|
|
1762
|
+
print("=== End Container Output ===")
|
|
1763
|
+
else:
|
|
1764
|
+
logging.warning("No container output captured")
|
|
1374
1765
|
|
|
1375
1766
|
used_memory_check(
|
|
1376
1767
|
test_name,
|
|
@@ -1428,13 +1819,30 @@ def process_self_contained_coordinator_stream(
|
|
|
1428
1819
|
full_result_path = "{}/{}".format(
|
|
1429
1820
|
temporary_dir_client, local_benchmark_output_filename
|
|
1430
1821
|
)
|
|
1822
|
+
elif "vector-db-benchmark" in benchmark_tool:
|
|
1823
|
+
# For vector-db-benchmark, look for summary JSON file
|
|
1824
|
+
import os
|
|
1825
|
+
summary_files = [f for f in os.listdir(temporary_dir_client) if f.endswith("-summary.json")]
|
|
1826
|
+
if summary_files:
|
|
1827
|
+
full_result_path = os.path.join(temporary_dir_client, summary_files[0])
|
|
1828
|
+
logging.info(f"Found vector-db-benchmark summary file: {summary_files[0]}")
|
|
1829
|
+
else:
|
|
1830
|
+
logging.warning("No vector-db-benchmark summary JSON file found")
|
|
1831
|
+
# Create empty results dict to avoid crash
|
|
1832
|
+
results_dict = {}
|
|
1833
|
+
|
|
1431
1834
|
logging.info(f"Reading results json from {full_result_path}")
|
|
1432
1835
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1836
|
+
if "vector-db-benchmark" in benchmark_tool and not os.path.exists(full_result_path):
|
|
1837
|
+
# Handle case where vector-db-benchmark didn't produce results
|
|
1838
|
+
results_dict = {}
|
|
1839
|
+
logging.warning("Vector-db-benchmark did not produce results file")
|
|
1840
|
+
else:
|
|
1841
|
+
with open(
|
|
1842
|
+
full_result_path,
|
|
1843
|
+
"r",
|
|
1844
|
+
) as json_file:
|
|
1845
|
+
results_dict = json.load(json_file)
|
|
1438
1846
|
print_results_table_stdout(
|
|
1439
1847
|
benchmark_config,
|
|
1440
1848
|
default_metrics,
|
|
@@ -1654,7 +2062,32 @@ def print_results_table_stdout(
|
|
|
1654
2062
|
]
|
|
1655
2063
|
results_matrix = extract_results_table(metrics, results_dict)
|
|
1656
2064
|
|
|
1657
|
-
|
|
2065
|
+
# Use resolved metric name for precision_summary metrics, otherwise use original path
|
|
2066
|
+
def get_display_name(x):
|
|
2067
|
+
# For precision_summary metrics with wildcards, construct the resolved path
|
|
2068
|
+
if (len(x) > 1 and
|
|
2069
|
+
isinstance(x[0], str) and
|
|
2070
|
+
"precision_summary" in x[0] and
|
|
2071
|
+
"*" in x[0]):
|
|
2072
|
+
|
|
2073
|
+
# Look for the precision level in the cleaned metrics logs
|
|
2074
|
+
# We need to find the corresponding cleaned metric to get the precision level
|
|
2075
|
+
# For now, let's extract it from the time series logs that we know are working
|
|
2076
|
+
# The pattern is: replace "*" with the actual precision level
|
|
2077
|
+
|
|
2078
|
+
# Since we know from logs that the precision level is available,
|
|
2079
|
+
# let's reconstruct it from the metric context path (x[1]) if available
|
|
2080
|
+
if len(x) > 1 and isinstance(x[1], str) and x[1].startswith("'") and x[1].endswith("'"):
|
|
2081
|
+
precision_level = x[1] # This should be something like "'1.0000'"
|
|
2082
|
+
resolved_path = x[0].replace("*", precision_level)
|
|
2083
|
+
return resolved_path
|
|
2084
|
+
|
|
2085
|
+
return x[0] # Use original path
|
|
2086
|
+
|
|
2087
|
+
results_matrix = [
|
|
2088
|
+
[get_display_name(x), f"{x[3]:.3f}"]
|
|
2089
|
+
for x in results_matrix
|
|
2090
|
+
]
|
|
1658
2091
|
writer = MarkdownTableWriter(
|
|
1659
2092
|
table_name=table_name,
|
|
1660
2093
|
headers=results_matrix_headers,
|
|
@@ -1668,14 +2101,19 @@ def print_redis_info_section(redis_conns):
|
|
|
1668
2101
|
if redis_conns is not None and len(redis_conns) > 0:
|
|
1669
2102
|
try:
|
|
1670
2103
|
redis_info = redis_conns[0].info()
|
|
2104
|
+
server_name = "redis"
|
|
2105
|
+
if "server_name" in redis_info:
|
|
2106
|
+
server_name = redis_info['server_name']
|
|
1671
2107
|
|
|
1672
2108
|
print("\n# Redis Server Information")
|
|
1673
2109
|
redis_info_data = [
|
|
1674
|
-
["
|
|
1675
|
-
["
|
|
1676
|
-
["
|
|
1677
|
-
["
|
|
1678
|
-
["
|
|
2110
|
+
[f"{server_name} version", redis_info.get(f"{server_name}_version", "unknown")],
|
|
2111
|
+
["redis version", redis_info.get("redis_version", "unknown")],
|
|
2112
|
+
["io_threads_active", redis_info.get("io_threads_active", "unknown")],
|
|
2113
|
+
[f"{server_name} Git SHA1", redis_info.get("redis_git_sha1", "unknown")],
|
|
2114
|
+
[f"{server_name} Git Dirty", str(redis_info.get("redis_git_dirty", "unknown"))],
|
|
2115
|
+
[f"{server_name} Build ID", redis_info.get("redis_build_id", "unknown")],
|
|
2116
|
+
[f"{server_name} Mode", redis_info.get("redis_mode", "unknown")],
|
|
1679
2117
|
["OS", redis_info.get("os", "unknown")],
|
|
1680
2118
|
["Arch Bits", str(redis_info.get("arch_bits", "unknown"))],
|
|
1681
2119
|
["GCC Version", redis_info.get("gcc_version", "unknown")],
|
|
@@ -1703,6 +2141,78 @@ def print_redis_info_section(redis_conns):
|
|
|
1703
2141
|
logging.warning(f"Failed to collect Redis server information: {e}")
|
|
1704
2142
|
|
|
1705
2143
|
|
|
2144
|
+
def get_supported_redis_commands(redis_conns):
|
|
2145
|
+
"""Get list of supported Redis commands from the server"""
|
|
2146
|
+
if redis_conns is not None and len(redis_conns) > 0:
|
|
2147
|
+
try:
|
|
2148
|
+
# Execute COMMAND to get all supported commands
|
|
2149
|
+
commands_info = redis_conns[0].execute_command("COMMAND")
|
|
2150
|
+
logging.info(f"COMMAND response type: {type(commands_info)}, length: {len(commands_info) if hasattr(commands_info, '__len__') else 'N/A'}")
|
|
2151
|
+
|
|
2152
|
+
# Extract command names
|
|
2153
|
+
supported_commands = set()
|
|
2154
|
+
|
|
2155
|
+
if isinstance(commands_info, dict):
|
|
2156
|
+
# COMMAND response is a dict with command names as keys
|
|
2157
|
+
for cmd_name in commands_info.keys():
|
|
2158
|
+
if isinstance(cmd_name, bytes):
|
|
2159
|
+
cmd_name = cmd_name.decode('utf-8')
|
|
2160
|
+
supported_commands.add(str(cmd_name).upper())
|
|
2161
|
+
elif isinstance(commands_info, (list, tuple)):
|
|
2162
|
+
# Fallback for list format (first element of each command info array)
|
|
2163
|
+
for cmd_info in commands_info:
|
|
2164
|
+
if isinstance(cmd_info, (list, tuple)) and len(cmd_info) > 0:
|
|
2165
|
+
cmd_name = cmd_info[0]
|
|
2166
|
+
if isinstance(cmd_name, bytes):
|
|
2167
|
+
cmd_name = cmd_name.decode('utf-8')
|
|
2168
|
+
supported_commands.add(str(cmd_name).upper())
|
|
2169
|
+
|
|
2170
|
+
logging.info(f"Retrieved {len(supported_commands)} supported Redis commands")
|
|
2171
|
+
|
|
2172
|
+
# Log some sample commands for debugging
|
|
2173
|
+
if supported_commands:
|
|
2174
|
+
sample_commands = sorted(list(supported_commands))[:10]
|
|
2175
|
+
logging.info(f"Sample commands: {sample_commands}")
|
|
2176
|
+
|
|
2177
|
+
# Check specifically for vector commands
|
|
2178
|
+
vector_commands = [cmd for cmd in supported_commands if cmd.startswith('V')]
|
|
2179
|
+
if vector_commands:
|
|
2180
|
+
logging.info(f"Vector commands found: {sorted(vector_commands)}")
|
|
2181
|
+
|
|
2182
|
+
return supported_commands
|
|
2183
|
+
except Exception as e:
|
|
2184
|
+
logging.warning(f"Failed to get supported Redis commands: {e}")
|
|
2185
|
+
logging.warning("Proceeding without command validation")
|
|
2186
|
+
return None
|
|
2187
|
+
return None
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
def check_test_command_support(benchmark_config, supported_commands):
|
|
2191
|
+
"""Check if all tested-commands in the benchmark config are supported"""
|
|
2192
|
+
if supported_commands is None:
|
|
2193
|
+
logging.warning("No supported commands list available, skipping command check")
|
|
2194
|
+
return True, []
|
|
2195
|
+
|
|
2196
|
+
if "tested-commands" not in benchmark_config:
|
|
2197
|
+
logging.info("No tested-commands specified in benchmark config")
|
|
2198
|
+
return True, []
|
|
2199
|
+
|
|
2200
|
+
tested_commands = benchmark_config["tested-commands"]
|
|
2201
|
+
unsupported_commands = []
|
|
2202
|
+
|
|
2203
|
+
for cmd in tested_commands:
|
|
2204
|
+
cmd_upper = cmd.upper()
|
|
2205
|
+
if cmd_upper not in supported_commands:
|
|
2206
|
+
unsupported_commands.append(cmd)
|
|
2207
|
+
|
|
2208
|
+
if unsupported_commands:
|
|
2209
|
+
logging.warning(f"Unsupported commands found: {unsupported_commands}")
|
|
2210
|
+
return False, unsupported_commands
|
|
2211
|
+
else:
|
|
2212
|
+
logging.info(f"All tested commands are supported: {tested_commands}")
|
|
2213
|
+
return True, []
|
|
2214
|
+
|
|
2215
|
+
|
|
1706
2216
|
def prepare_overall_total_test_results(
|
|
1707
2217
|
benchmark_config,
|
|
1708
2218
|
default_metrics,
|
|
@@ -1721,8 +2231,25 @@ def prepare_overall_total_test_results(
|
|
|
1721
2231
|
None,
|
|
1722
2232
|
)
|
|
1723
2233
|
current_test_results_matrix = extract_results_table(metrics, results_dict)
|
|
2234
|
+
|
|
2235
|
+
# Use the same display name logic as in the individual test results
|
|
2236
|
+
def get_overall_display_name(x):
|
|
2237
|
+
# For precision_summary metrics with wildcards, construct the resolved path
|
|
2238
|
+
if (len(x) > 1 and
|
|
2239
|
+
isinstance(x[0], str) and
|
|
2240
|
+
"precision_summary" in x[0] and
|
|
2241
|
+
"*" in x[0]):
|
|
2242
|
+
|
|
2243
|
+
# Reconstruct resolved path from metric context path (x[1]) if available
|
|
2244
|
+
if len(x) > 1 and isinstance(x[1], str) and x[1].startswith("'") and x[1].endswith("'"):
|
|
2245
|
+
precision_level = x[1] # This should be something like "'1.0000'"
|
|
2246
|
+
resolved_path = x[0].replace("*", precision_level)
|
|
2247
|
+
return resolved_path
|
|
2248
|
+
|
|
2249
|
+
return x[0] # Use original path
|
|
2250
|
+
|
|
1724
2251
|
current_test_results_matrix = [
|
|
1725
|
-
[test_name, x
|
|
2252
|
+
[test_name, get_overall_display_name(x), f"{x[3]:.3f}"] for x in current_test_results_matrix
|
|
1726
2253
|
]
|
|
1727
2254
|
overall_results_matrix.extend(current_test_results_matrix)
|
|
1728
2255
|
|
|
@@ -1747,6 +2274,7 @@ def data_prepopulation_step(
|
|
|
1747
2274
|
password=None,
|
|
1748
2275
|
oss_cluster_api_enabled=False,
|
|
1749
2276
|
unix_socket="",
|
|
2277
|
+
timeout_buffer=60,
|
|
1750
2278
|
):
|
|
1751
2279
|
result = True
|
|
1752
2280
|
# setup the benchmark
|
|
@@ -1808,13 +2336,21 @@ def data_prepopulation_step(
|
|
|
1808
2336
|
preload_command_str = (
|
|
1809
2337
|
"taskset -c " + client_cpuset_cpus + " " + preload_command_str
|
|
1810
2338
|
)
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2339
|
+
|
|
2340
|
+
# Calculate timeout for preload process
|
|
2341
|
+
process_timeout = calculate_process_timeout(preload_command_str, timeout_buffer)
|
|
2342
|
+
|
|
2343
|
+
# Run with timeout
|
|
2344
|
+
success, client_container_stdout, stderr = run_local_command_with_timeout(
|
|
2345
|
+
preload_command_str,
|
|
2346
|
+
process_timeout,
|
|
2347
|
+
"memtier preload"
|
|
1815
2348
|
)
|
|
1816
|
-
|
|
1817
|
-
|
|
2349
|
+
|
|
2350
|
+
if not success:
|
|
2351
|
+
logging.error(f"Memtier preload failed: {stderr}")
|
|
2352
|
+
result = False
|
|
2353
|
+
return result
|
|
1818
2354
|
|
|
1819
2355
|
move_command = "mv {} {}".format(
|
|
1820
2356
|
local_benchmark_output_filename, temporary_dir
|