Skip to content

Commit 9d485e8

Browse files
[add] Refactored run-local and run-remote to use more common flows. Preparing run-remote to allow oss-cluster benchmarks (#156)
1 parent a7d2ec3 commit 9d485e8

35 files changed

+2099
-1498
lines changed

redisbench_admin/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,11 @@
44
# All rights reserved.
55
#
66

7-
__version__ = "0.1.30"
7+
# This attribute is the only one place that the version number is written down,
8+
# so there is only one place to change it when the version number changes.
9+
import pkg_resources
10+
11+
try:
12+
__version__ = pkg_resources.get_distribution("redisbench-admin").version
13+
except (pkg_resources.DistributionNotFound, AttributeError):
14+
__version__ = "99.99.99" # like redis modules

redisbench_admin/cli.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,17 @@ def main():
123123
)
124124

125125
if requested_tool == "run-local":
126-
run_local_command_logic(args)
126+
run_local_command_logic(args, project_name, project_version)
127127
if requested_tool == "run-remote":
128-
run_remote_command_logic(args)
128+
run_remote_command_logic(args, project_name, project_version)
129129
if requested_tool == "export":
130-
export_command_logic(args)
130+
export_command_logic(args, project_name, project_version)
131131
if requested_tool == "extract":
132-
extract_command_logic(args)
132+
extract_command_logic(args, project_name, project_version)
133133
if requested_tool == "watchdog":
134-
watchdog_command_logic(args)
134+
watchdog_command_logic(args, project_name, project_version)
135135
if requested_tool == "compare":
136-
compare_command_logic(args)
136+
compare_command_logic(args, project_name, project_version)
137137

138138

139139
def print_invalid_tool_option(requested_tool, valid_tool_options):

redisbench_admin/compare/args.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
) = extract_git_vars()
2525

2626
_, NOW_UTC, _ = get_start_time_vars()
27-
LAST_24_HOURS_UTC = NOW_UTC - (24 * 60 * 60 * 1000)
27+
LAST_WEEK_UTC = NOW_UTC - (24 * 90 * 60 * 60 * 1000)
2828

2929

3030
def create_compare_arguments(parser):
@@ -58,6 +58,6 @@ def create_compare_arguments(parser):
5858
parser.add_argument(
5959
"--redistimeseries_pass", type=str, default=PERFORMANCE_RTS_AUTH
6060
)
61-
parser.add_argument("--from_timestamp", type=int, default=LAST_24_HOURS_UTC)
61+
parser.add_argument("--from_timestamp", type=int, default=LAST_WEEK_UTC)
6262
parser.add_argument("--to_timestamp", type=int, default=NOW_UTC)
6363
return parser

redisbench_admin/compare/compare.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
from redisbench_admin.utils.utils import get_ts_metric_name
1515

1616

17-
def compare_command_logic(args):
17+
def compare_command_logic(args, project_name, project_version):
18+
logging.info(
19+
"Using: {project_name} {project_version}".format(
20+
project_name=project_name, project_version=project_version
21+
)
22+
)
1823
logging.info("Checking connection to RedisTimeSeries.")
1924
rts = Client(
2025
host=args.redistimeseries_host,
@@ -59,6 +64,9 @@ def compare_command_logic(args):
5964
)
6065
profilers_artifacts_matrix = []
6166
detected_regressions = []
67+
total_improvements = 0
68+
total_stable = 0
69+
total_regressions = 0
6270
for test_name in test_names:
6371

6472
test_name = test_name.decode()
@@ -113,12 +121,24 @@ def compare_command_logic(args):
113121
) * 100.0
114122
if baseline_v != "N/A" or comparison_v != "N/A":
115123
detected_regression = False
124+
detected_improvement = False
116125
if (
117126
percentage_change < 0.0
118127
and percentage_change < -args.regressions_percent_lower_limit
119128
):
120129
detected_regression = True
130+
total_regressions = total_regressions + 1
121131
detected_regressions.append(test_name)
132+
if (
133+
percentage_change > 0.0
134+
and percentage_change > args.regressions_percent_lower_limit
135+
):
136+
detected_improvement = True
137+
total_improvements = total_improvements + 1
138+
139+
if detected_improvement is False and detected_regression is False:
140+
total_stable = total_stable + 1
141+
122142
if args.print_regressions_only is False or detected_regression:
123143
profilers_artifacts_matrix.append(
124144
[
@@ -144,13 +164,25 @@ def compare_command_logic(args):
144164
value_matrix=profilers_artifacts_matrix,
145165
)
146166
writer.write_table()
147-
total_regressions = len(detected_regressions)
167+
if total_stable > 0:
168+
logging.info(
169+
"Detected a total of {} stable tests between versions.".format(
170+
total_stable,
171+
)
172+
)
173+
if total_improvements > 0:
174+
logging.info(
175+
"Detected a total of {} improvements above the improvement water line (> {} %%)".format(
176+
total_improvements, args.regressions_percent_lower_limit
177+
)
178+
)
148179
if total_regressions > 0:
149180
logging.warning(
150-
"Detected a total of {} regressions. Printing BENCHMARK env var compatible list".format(
151-
total_regressions
181+
"Detected a total of {} regressions bellow the regression water line (< -{} %%)".format(
182+
total_regressions, args.regressions_percent_lower_limit
152183
)
153184
)
185+
logging.warning("Printing BENCHMARK env var compatible list")
154186
logging.warning(
155187
"BENCHMARK={}".format(
156188
",".join(["{}.yml".format(x) for x in detected_regressions])

redisbench_admin/export/export.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
import json
9+
import logging
910
import os
1011

1112
import redis
@@ -19,7 +20,12 @@
1920
from redisbench_admin.utils.utils import retrieve_local_or_remote_input_json
2021

2122

22-
def export_command_logic(args):
23+
def export_command_logic(args, project_name, project_version):
24+
logging.info(
25+
"Using: {project_name} {project_version}".format(
26+
project_name=project_name, project_version=project_version
27+
)
28+
)
2329
benchmark_files = args.benchmark_result_files
2430
local_path = os.path.abspath(args.local_dir)
2531
results_format = args.results_format

redisbench_admin/extract/extract.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#
66

77
import json
8+
import logging
89
import time
910

1011
import redis
@@ -14,7 +15,12 @@ def current_milli_time():
1415
return round(time.time() * 1000)
1516

1617

17-
def extract_command_logic(args):
18+
def extract_command_logic(args, project_name, project_version):
19+
logging.info(
20+
"Using: {project_name} {project_version}".format(
21+
project_name=project_name, project_version=project_version
22+
)
23+
)
1824
redis_url = args.redis_url
1925
output_json = args.output_tags_json
2026
redis_client = redis.from_url(redis_url)

redisbench_admin/run/aibench_run_inference_redisai_vision/aibench_run_inference_redisai_vision.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,18 @@ def prepare_aibench_benchmark_command(
3737

3838
command_str = " ".join(command_arr)
3939
return command_arr, command_str
40+
41+
42+
def extract_aibench_extra_links(benchmark_config, benchmark_tool):
43+
remote_tool_link = "/tmp/{}".format(benchmark_tool)
44+
tool_link = (
45+
"https://s3.amazonaws.com/benchmarks.redislabs/"
46+
+ "tools/redisai/aibench/{}_linux_amd64".format(benchmark_tool)
47+
)
48+
queries_file_link = None
49+
for entry in benchmark_config["clientconfig"]:
50+
if "parameters" in entry:
51+
for parameter in entry["parameters"]:
52+
if "file" in parameter:
53+
queries_file_link = parameter["file"]
54+
return queries_file_link, remote_tool_link, tool_link

redisbench_admin/run/cluster.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# BSD 3-Clause License
2+
#
3+
# Copyright (c) 2021., Redis Labs Modules
4+
# All rights reserved.
5+
#
6+
import logging
7+
8+
import redis
9+
10+
11+
def cluster_init_steps(args, clusterconfig, local_module_file, r_conns, shard_count):
12+
startup_nodes = []
13+
for p in range(args.port, args.port + shard_count):
14+
primary_conn = redis.StrictRedis(port=p)
15+
primary_conn.execute_command("DEBUG RELOAD NOSAVE")
16+
r_conns.append(primary_conn)
17+
startup_nodes.append({"host": "127.0.0.1", "port": "{}".format(p)})
18+
if clusterconfig is not None:
19+
if "init_commands" in clusterconfig:
20+
for command_group in clusterconfig["init_commands"]:
21+
skip = False
22+
if "when_modules_present" in command_group:
23+
m_found = False
24+
for module_required in command_group["when_modules_present"]:
25+
if type(local_module_file) == list:
26+
for local_m in local_module_file:
27+
if module_required in local_m:
28+
m_found = True
29+
logging.info(
30+
"Required module {} found in {}".format(
31+
module_required,
32+
local_m,
33+
)
34+
)
35+
else:
36+
if module_required in local_module_file:
37+
m_found = True
38+
logging.info(
39+
"Required module {} found in {}".format(
40+
module_required,
41+
local_module_file,
42+
)
43+
)
44+
skip = not (m_found)
45+
if skip is False:
46+
for command in command_group["commands"]:
47+
for conn_n, rc in enumerate(r_conns):
48+
rc.execute_command(command)
49+
logging.info(
50+
"Cluster node {}: sent command {}".format(
51+
conn_n + 1, command
52+
)
53+
)
54+
else:
55+
logging.info(
56+
"Skipping to send the command group: {}.".format(
57+
command_group["commands"],
58+
)
59+
+ "Given the when_modules_present condition ({}) is not true.".format(
60+
command_group["when_modules_present"],
61+
)
62+
)
63+
return startup_nodes
64+
65+
66+
# noinspection PyBroadException
67+
def spin_up_redis_cluster_remote_redis(
68+
benchmark_config,
69+
server_public_ip,
70+
username,
71+
private_key,
72+
local_module_file,
73+
remote_module_file,
74+
remote_dataset_file,
75+
logname,
76+
dirname,
77+
redis_configuration_parameters,
78+
dbdir_folder,
79+
shard_count,
80+
port,
81+
):
82+
raise Exception(
83+
"Remote cluster is still not implemented =(. We're working hard to get it ASAP =)!!"
84+
)

redisbench_admin/run/common.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# All rights reserved.
55
#
66
import csv
7+
import datetime
78
import datetime as dt
89
import logging
910
import os
@@ -23,8 +24,14 @@
2324
prepare_tsbs_benchmark_command,
2425
)
2526
from redisbench_admin.run.ycsb.ycsb import prepare_ycsb_benchmark_command
27+
from redisbench_admin.run_remote.remote_helpers import (
28+
extract_module_semver_from_info_modules_cmd,
29+
)
2630
from redisbench_admin.utils.benchmark_config import (
2731
parse_exporter_timemetric,
32+
parse_exporter_metrics_definition,
33+
parse_exporter_timemetric_definition,
34+
check_required_modules,
2835
)
2936
from redisbench_admin.utils.remote import (
3037
execute_remote_commands,
@@ -285,7 +292,9 @@ def execute_init_commands(benchmark_config, r, dbconfig_keyname="dbconfig"):
285292
)
286293

287294

288-
def extract_test_feasible_setups(benchmark_config, param, default_specs):
295+
def extract_test_feasible_setups(
296+
benchmark_config, param, default_specs, backwards_compatible=True
297+
):
289298
feasible_setups_map = {}
290299
if param in benchmark_config:
291300
feasible_setups_list = benchmark_config[param]
@@ -295,10 +304,82 @@ def extract_test_feasible_setups(benchmark_config, param, default_specs):
295304
for setup in default_specs["setups"]:
296305
if setup_name == setup["name"]:
297306
feasible_setups_map[setup_name] = setup
307+
if len(feasible_setups_map.keys()) == 0 and backwards_compatible:
308+
feasible_setups_map["oss-standalone"] = {
309+
"name": "oss-standalone",
310+
"type": "oss-standalone",
311+
"redis_topology": {"primaries": 1, "replicas": 0},
312+
"resources": {"requests": {"cpu": "1000m"}, "limits": {"cpu": "2000m"}},
313+
}
314+
logging.info(
315+
"Using a backwards compatible 'oss-standalone' setup, with settings: {}".format(
316+
feasible_setups_map["oss-standalone"]
317+
)
318+
)
319+
298320
return feasible_setups_map
299321

300322

301323
def get_setup_type_and_primaries_count(setup_settings):
302324
setup_type = setup_settings["type"]
303325
shard_count = setup_settings["redis_topology"]["primaries"]
304326
return setup_type, shard_count
327+
328+
329+
def merge_default_and_config_metrics(
330+
benchmark_config, default_metrics, exporter_timemetric_path
331+
):
332+
metrics = default_metrics
333+
if "exporter" in benchmark_config:
334+
extra_metrics = parse_exporter_metrics_definition(benchmark_config["exporter"])
335+
metrics.extend(extra_metrics)
336+
extra_timemetric_path = parse_exporter_timemetric_definition(
337+
benchmark_config["exporter"]
338+
)
339+
if extra_timemetric_path is not None:
340+
exporter_timemetric_path = extra_timemetric_path
341+
return exporter_timemetric_path, metrics
342+
343+
344+
def run_redis_pre_steps(benchmark_config, r, required_modules):
345+
stdout = r.execute_command("info modules")
346+
(
347+
module_names,
348+
artifact_versions,
349+
) = extract_module_semver_from_info_modules_cmd(stdout)
350+
check_required_modules(module_names, required_modules)
351+
# run initialization commands before benchmark starts
352+
logging.info("Running initialization commands before benchmark starts.")
353+
execute_init_commands_start_time = datetime.datetime.now()
354+
execute_init_commands(benchmark_config, r)
355+
execute_init_commands_duration_seconds = (
356+
datetime.datetime.now() - execute_init_commands_start_time
357+
).seconds
358+
logging.info(
359+
"Running initialization commands took {} secs.".format(
360+
execute_init_commands_duration_seconds
361+
)
362+
)
363+
return artifact_versions[0]
364+
365+
366+
def dso_check(dso, local_module_file):
367+
if dso is None:
368+
logging.warning("No dso specified for perf analysis {}".format(dso))
369+
if local_module_file is not None:
370+
371+
if type(local_module_file) == str:
372+
dso = local_module_file
373+
logging.warning(
374+
"Using provided module = {} to specify dso".format(
375+
local_module_file
376+
)
377+
)
378+
if type(local_module_file) == list:
379+
dso = local_module_file[0]
380+
logging.warning(
381+
"Using first module = {} to specify dso".format(
382+
local_module_file[0]
383+
)
384+
)
385+
return dso

0 commit comments

Comments
 (0)