Skip to content

Commit b79e7a8

Browse files
Enabled memtier_benchmark SPEC (#307)
* In case of remote rdb fetch and remote run will copy directly from remote file to DB machine (remove extra hop) * Only call check_if_needs_remote_fetch when remote is False * Only call check_if_needs_remote_fetch when remote is False * Enabled memtier_benchmark SPEC * Added test for extract_benchmark_type_from_config() * flake8 check fix on run_remote_client_tool() * Bumping version to 0.7.7 * Added memtier_benchmark to allowed tools list * Fixed test_prepare_ann_benchmark_command() missing args test
1 parent 3d64bf0 commit b79e7a8

File tree

11 files changed

+184
-30
lines changed

11 files changed

+184
-30
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "redisbench-admin"
3-
version = "0.7.6"
3+
version = "0.7.7"
44
description = "Redis benchmark run helper. A wrapper around Redis and Redis Modules benchmark tools ( ftsb_redisearch, memtier_benchmark, redis-benchmark, aibench, etc... )."
55
authors = ["filipecosta90 <filipecosta.90@gmail.com>","Redis Performance Group <performance@redis.com>"]
66
readme = "README.md"

redisbench_admin/run/args.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def common_run_args(parser):
6060
parser.add_argument(
6161
"--allowed-tools",
6262
type=str,
63-
default="redis-benchmark,redisgraph-benchmark-go,ycsb,"
63+
default="memtier_benchmark,redis-benchmark,redisgraph-benchmark-go,ycsb,"
6464
+ "tsbs_run_queries_redistimeseries,tsbs_load_redistimeseries,"
6565
+ "ftsb_redisearch,"
6666
+ "aibench_run_inference_redisai_vision,ann-benchmarks",

redisbench_admin/run/memtier_benchmark/memtier_benchmark.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import logging
88
import re
99
import subprocess
10-
10+
import shlex
1111
from redisbench_admin.utils.remote import execute_remote_commands
1212

1313

@@ -26,13 +26,16 @@ def prepare_memtier_benchmark_command(
2626

2727
if cluster_api_enabled:
2828
command_arr.extend(["--cluster-mode"])
29-
30-
for k in benchmark_config["parameters"]:
31-
for kk in k.keys():
32-
command_arr.extend(["--{}".format(kk), str(k[kk])])
29+
if "parameters" in benchmark_config:
30+
for k in benchmark_config["parameters"]:
31+
for kk in k.keys():
32+
command_arr.extend(["--{}".format(kk), str(k[kk])])
3333

3434
command_arr.extend(["--json-out-file", result_file])
3535
command_str = " ".join(command_arr)
36+
if "arguments" in benchmark_config:
37+
command_str = command_str + " " + benchmark_config["arguments"]
38+
command_arr.extend(shlex.split(benchmark_config["arguments"]))
3639
return command_arr, command_str
3740

3841

redisbench_admin/run_remote/remote_client.py

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
post_process_remote_run,
1717
)
1818
from redisbench_admin.utils.benchmark_config import extract_benchmark_tool_settings
19-
from redisbench_admin.utils.redisgraph_benchmark_go import setup_remote_benchmark_ann
19+
from redisbench_admin.utils.redisgraph_benchmark_go import (
20+
setup_remote_benchmark_ann,
21+
get_redisbench_admin_remote_path,
22+
)
2023
from redisbench_admin.utils.remote import (
2124
execute_remote_commands,
2225
fetch_file_from_remote_setup,
@@ -100,6 +103,34 @@ def run_remote_client_tool(
100103
if benchmark_tool == "redis-benchmark":
101104
tmp = local_bench_fname
102105
local_bench_fname = "result.csv"
106+
commands = [command_str]
107+
local_output_artifacts = []
108+
remote_output_artifacts = []
109+
if "ann" in benchmark_tool:
110+
[recv_exit_status, stdout, stderr] = get_redisbench_admin_remote_path(
111+
client_public_ip, username, private_key, client_ssh_port
112+
)[0]
113+
pkg_path = stdout[0].strip()
114+
benchmark_suffix = local_bench_fname[: len(local_bench_fname) - 5]
115+
create_website_path = pkg_path + "/run/ann/pkg/"
116+
logging.info("Remote create website path: {}".format(create_website_path))
117+
website_outputdir = "/tmp/website-{}".format(benchmark_suffix)
118+
website_outputdir_zip = "/tmp/website-{}.zip".format(benchmark_suffix)
119+
mkdir_command = "mkdir -p {}".format(website_outputdir)
120+
create_website_command = (
121+
"cd {} && sudo python3 create_website.py --outputdir {}".format(
122+
create_website_path, website_outputdir
123+
)
124+
)
125+
zip_website_command = "zip -r {} {}".format(
126+
website_outputdir_zip, website_outputdir
127+
)
128+
commands.append(mkdir_command)
129+
commands.append(create_website_command)
130+
commands.append(zip_website_command)
131+
local_output_artifacts.append(website_outputdir_zip)
132+
remote_output_artifacts.append(website_outputdir_zip)
133+
103134
benchmark_start_time = datetime.datetime.now()
104135
# run the benchmark
105136
remote_run_result, stdout, _ = run_remote_benchmark(
@@ -108,7 +139,7 @@ def run_remote_client_tool(
108139
private_key,
109140
remote_results_file,
110141
local_bench_fname,
111-
command_str,
142+
commands,
112143
client_ssh_port,
113144
)
114145
benchmark_end_time = datetime.datetime.now()
@@ -159,40 +190,74 @@ def run_remote_benchmark(
159190
client_public_ip,
160191
username,
161192
private_key,
162-
remote_results_file,
163-
local_results_file,
164-
command,
193+
remote_results_files,
194+
local_results_files,
195+
commands,
165196
ssh_port=22,
166197
):
167198
remote_run_result = False
168199
res = execute_remote_commands(
169-
client_public_ip, username, private_key, [command], ssh_port
200+
client_public_ip, username, private_key, commands, ssh_port
170201
)
171-
recv_exit_status, stdout, stderr = res[0]
202+
recv_exit_status, _, _ = res[0]
172203

173204
if recv_exit_status != 0:
174205
logging.error(
175206
"Exit status of remote command execution {}. Printing stdout and stderr".format(
176207
recv_exit_status
177208
)
178209
)
179-
logging.error("remote process stdout: {}".format(stdout))
180-
logging.error("remote process stderr: {}".format(stderr))
210+
stderr, stdout = print_commands_outputs(commands, True, res)
181211
else:
182212
logging.info(
183213
"Remote process exited normally. Exit code {}. Printing stdout.".format(
184214
recv_exit_status
185215
)
186216
)
187-
logging.info("remote process stdout: {}".format(stdout))
217+
stderr, stdout = print_commands_outputs(commands, False, res)
218+
188219
logging.info("Extracting the benchmark results")
189220
remote_run_result = True
190-
if "ycsb" not in command:
191-
fetch_file_from_remote_setup(
192-
client_public_ip,
193-
username,
194-
private_key,
195-
local_results_file,
196-
remote_results_file,
197-
)
221+
if "ycsb" not in commands[0]:
222+
if type(local_results_files) == str:
223+
local_results_file = local_results_files
224+
remote_results_file = remote_results_files
225+
fetch_file_from_remote_setup(
226+
client_public_ip,
227+
username,
228+
private_key,
229+
local_results_file,
230+
remote_results_file,
231+
)
232+
if type(local_results_files) == list:
233+
assert len(local_results_files) == len(remote_results_files)
234+
for pos, local_results_file in enumerate(local_results_files):
235+
remote_results_file = remote_results_files[pos]
236+
fetch_file_from_remote_setup(
237+
client_public_ip,
238+
username,
239+
private_key,
240+
local_results_file,
241+
remote_results_file,
242+
)
198243
return remote_run_result, stdout, stderr
244+
245+
246+
def print_commands_outputs(commands, print_err, res):
247+
bench_stdout = ""
248+
bench_stderr = ""
249+
for pos, res_tuple in enumerate(res):
250+
recv_exit_status, stdout, stderr = res_tuple
251+
if pos == 0:
252+
stderr, stdout = stderr, stdout
253+
logging.info(
254+
"Exit status for command {}: {}".format(commands[pos], recv_exit_status)
255+
)
256+
logging.info("\tremote process stdout:")
257+
for line in stdout:
258+
print(line.strip())
259+
if print_err:
260+
logging.error("\tremote process stderr:")
261+
for line in stderr:
262+
print(line.strip())
263+
return bench_stderr, bench_stdout

redisbench_admin/run_remote/run_remote.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ def run_remote_command_logic(args, project_name, project_version):
186186
profiler_dashboard_table_headers = ["Setup", "Test-case", "Grafana Dashboard"]
187187
profiler_dashboard_links = []
188188

189+
benchmark_artifacts_table_name = "Benchmark client artifacts"
190+
benchmark_artifacts_table_headers = ["Setup", "Test-case", "Artifact", "link"]
191+
benchmark_artifacts_links = []
192+
189193
# contains the overall target-tables ( if any target is defined )
190194
overall_tables = {}
191195

@@ -762,6 +766,15 @@ def run_remote_command_logic(args, project_name, project_version):
762766
test_name
763767
)
764768
)
769+
770+
if len(benchmark_artifacts_links) > 0:
771+
writer = MarkdownTableWriter(
772+
table_name=benchmark_artifacts_table_name,
773+
headers=benchmark_artifacts_table_headers,
774+
value_matrix=benchmark_artifacts_links,
775+
)
776+
writer.write_table()
777+
765778
if args.enable_profilers:
766779
writer = MarkdownTableWriter(
767780
table_name=profiler_dashboard_table_name,

redisbench_admin/utils/benchmark_config.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,16 @@ def extract_benchmark_type_from_config(
301301
benchmark_config_present = False
302302
benchmark_type = None
303303
if config_key in benchmark_config:
304-
benchmark_config_present = True
305-
for entry in benchmark_config[config_key]:
306-
if benchmark_type_key in entry:
307-
benchmark_type = entry[benchmark_type_key]
304+
305+
if type(benchmark_config[config_key]) == list:
306+
for entry in benchmark_config[config_key]:
307+
if benchmark_type_key in entry:
308+
benchmark_type = entry[benchmark_type_key]
309+
benchmark_config_present = True
310+
elif type(benchmark_config[config_key]) == dict:
311+
if benchmark_type_key in benchmark_config[config_key]:
312+
benchmark_type = benchmark_config[config_key][benchmark_type_key]
313+
benchmark_config_present = True
308314
if benchmark_type is None:
309315
logging.info(
310316
"Given the '{}' info was not present on {} we will assume the most inclusive default: '{}'".format(

tests/test_ann.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def test_prepare_ann_benchmark_command():
2121
benchmark_config["clientconfig"],
2222
"result.json",
2323
".",
24+
"ann",
2425
)
2526
assert (
2627
" ".join(command_arr[3:])

tests/test_benchmark_config.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
results_dict_kpi_check,
77
check_required_modules,
88
extract_redis_dbconfig_parameters,
9+
extract_benchmark_type_from_config,
910
)
1011

1112

@@ -113,3 +114,21 @@ def test_extract_redis_configuration_parameters():
113114
"redistimeseries": {"CHUNK_SIZE_BYTES": 128}
114115
}
115116
assert dbconfig_present == True
117+
118+
119+
def test_extract_benchmark_type_from_config():
120+
with open("./tests/test_data/vecsim-memtier.yml", "r") as yml_file:
121+
benchmark_config = yaml.safe_load(yml_file)
122+
benchmark_config_present, benchmark_type = extract_benchmark_type_from_config(
123+
benchmark_config
124+
)
125+
assert benchmark_type == "read-only"
126+
assert benchmark_config_present == True
127+
128+
with open("./tests/test_data/redis-benchmark.yml", "r") as yml_file:
129+
benchmark_config = yaml.safe_load(yml_file)
130+
benchmark_config_present, benchmark_type = extract_benchmark_type_from_config(
131+
benchmark_config
132+
)
133+
assert benchmark_type == "mixed"
134+
assert benchmark_config_present == False

tests/test_data/vecsim-memtier.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
name: "vecsim_hybrid_HNSW_05"
3+
description: "hybrid hnsw with 0.5% filtered results"
4+
remote:
5+
- type: oss-standalone
6+
- setup: redisearch-m5d
7+
dbconfig:
8+
- dataset_name: "hybrid-glove100-index-1"
9+
- dataset: "https://s3.amazonaws.com/benchmarks.redislabs/redisearch/datasets/vecsim/hybrid-glove100-index-1.rdb"
10+
- dataset_load_timeout_secs: 1800
11+
setups:
12+
- oss-standalone
13+
clientconfig:
14+
benchmark_type: "read-only"
15+
tool: memtier_benchmark
16+
arguments: "--command \"FT.SEARCH idx 'text0=>[KNN $k @hnsw_vector $BLOB]' PARAMS 4 k 10 BLOB aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" --test-time 180 -c 8 -t 2 --hide-histogram"

tests/test_memtier_benchmark.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# BSD 3-Clause License
2+
#
3+
# Copyright (c) 2022., Redis Labs Modules
4+
# All rights reserved.
5+
#
6+
import yaml
7+
8+
from redisbench_admin.run.memtier_benchmark.memtier_benchmark import (
9+
prepare_memtier_benchmark_command,
10+
)
11+
12+
13+
def test_prepare_memtier_benchmark_command():
14+
with open("./tests/test_data/vecsim-memtier.yml", "r") as yml_file:
15+
benchmark_config = yaml.safe_load(yml_file)
16+
command_arr, command_str = prepare_memtier_benchmark_command(
17+
"memtier_benchmark",
18+
"localhost",
19+
"6380",
20+
benchmark_config["clientconfig"],
21+
False,
22+
"result.json",
23+
)
24+
assert (
25+
command_str
26+
== "memtier_benchmark -s localhost -p 6380 --hide-histogram --json-out-file result.json --command \"FT.SEARCH idx 'text0=>[KNN $k @hnsw_vector $BLOB]' PARAMS 4 k 10 BLOB aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" --test-time 180 -c 8 -t 2 --hide-histogram"
27+
)
28+
assert (
29+
command_arr[9]
30+
== "FT.SEARCH idx 'text0=>[KNN $k @hnsw_vector $BLOB]' PARAMS 4 k 10 BLOB aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
31+
)
32+
assert len(command_arr) == 17

0 commit comments

Comments
 (0)