Skip to content

Commit a7924bc

Browse files
YCSB local run working as expected. Improved remote tool specification on YAML (#75)
* [wip] YCSB local run ( requires post processing of results ) * [add] Made tool source remote config more verbose/easy to use * Bumping version from 0.1.62 to 0.1.63
1 parent 98d0f89 commit a7924bc

File tree

11 files changed

+278
-74
lines changed

11 files changed

+278
-74
lines changed

poetry.lock

+59-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "redisbench-admin"
3-
version = "0.1.62"
3+
version = "0.1.63"
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 <[email protected]>"]
66
readme = "README.md"
@@ -33,6 +33,7 @@ pytest-cov = "^2.9.0"
3333
codecov = "^2.1.4"
3434
black = "^20.8b1"
3535
flake8 = "^3.9.1"
36+
docker = "^5.0.0"
3637

3738
[build-system]
3839
requires = ["poetry>=0.12"]

redisbench_admin/run/common.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
def extract_benchmark_tool_settings(benchmark_config):
3030
benchmark_tool = None
3131
benchmark_tool_source = None
32+
benchmark_tool_source_inner_path = None
3233
benchmark_min_tool_version = None
3334
benchmark_min_tool_version_major = None
3435
benchmark_min_tool_version_minor = None
@@ -38,7 +39,12 @@ def extract_benchmark_tool_settings(benchmark_config):
3839
if "tool" in entry:
3940
benchmark_tool = entry["tool"]
4041
if "tool_source" in entry:
41-
benchmark_tool_source = entry["tool_source"]
42+
for inner_entry in entry["tool_source"]:
43+
if "remote" in inner_entry:
44+
benchmark_tool_source = inner_entry["remote"]
45+
if "bin_path" in inner_entry:
46+
benchmark_tool_source_inner_path = inner_entry["bin_path"]
47+
4248
if "min-tool-version" in entry:
4349
benchmark_min_tool_version = entry["min-tool-version"]
4450
p = re.compile(r"(\d+)\.(\d+)\.(\d+)")
@@ -60,6 +66,7 @@ def extract_benchmark_tool_settings(benchmark_config):
6066
benchmark_min_tool_version_patch,
6167
benchmark_tool,
6268
benchmark_tool_source,
69+
benchmark_tool_source_inner_path,
6370
)
6471

6572

redisbench_admin/run/ycsb/ycsb.py

+34-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import csv
2+
import re
3+
4+
15
def prepare_ycsb_benchmark_command(
26
executable_path: str,
37
server_private_ip: object,
@@ -29,7 +33,7 @@ def prepare_ycsb_benchmark_command(
2933
step = k["step"]
3034
if "workload" in k:
3135
workload = k["workload"]
32-
if workload.startswith("./"):
36+
if current_workdir is not None and workload.startswith("./"):
3337
workload = "{}{}".format(current_workdir, workload[1:])
3438
if "threads" in k:
3539
threads = k["threads"]
@@ -49,9 +53,36 @@ def prepare_ycsb_benchmark_command(
4953

5054
for prop in override_workload_properties:
5155
for k, v in prop.items():
52-
if type(v) == str and v.startswith("./"):
56+
if current_workdir is not None and type(v) == str and v.startswith("./"):
5357
v = "{}{}".format(current_workdir, v[1:])
54-
command_arr.extend(["-p", '"{}={}"'.format(k, v)])
58+
command_arr.extend(["-p", "{}={}".format(k, v)])
5559

5660
command_str = " ".join(command_arr)
5761
return command_arr, command_str
62+
63+
64+
def post_process_ycsb_results(stdout, start_time_ms, start_time_str):
65+
results_dict = {
66+
"Tests": {},
67+
"StartTime": start_time_ms,
68+
"StartTimeHuman": start_time_str,
69+
}
70+
if type(stdout) == bytes:
71+
stdout = stdout.decode("ascii")
72+
csv_data = list(csv.reader(stdout.splitlines(), delimiter=","))
73+
start_row = 0
74+
for row in csv_data:
75+
if len(row) >= 1:
76+
if "[OVERALL]" in row[0]:
77+
break
78+
start_row = start_row + 1
79+
for row in csv_data[start_row:]:
80+
if len(row) >= 3:
81+
op_group = row[0].strip()[1:-1]
82+
metric_name = row[1].strip()
83+
metric_name = re.sub("[^0-9a-zA-Z]+", "_", metric_name)
84+
value = row[2].strip()
85+
if op_group not in results_dict["Tests"]:
86+
results_dict["Tests"][op_group] = {}
87+
results_dict["Tests"][op_group][metric_name] = value
88+
return results_dict

redisbench_admin/run_local/run_local.py

+81-52
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import os
44
import pathlib
55
import shutil
6-
import stat
76
import subprocess
87
import sys
98
import tempfile
@@ -22,6 +21,7 @@
2221
redis_benchmark_from_stdout_csv_to_json,
2322
redis_benchmark_ensure_min_version_local,
2423
)
24+
from redisbench_admin.run.ycsb.ycsb import post_process_ycsb_results
2525
from redisbench_admin.utils.local import (
2626
spin_up_local_redis,
2727
get_local_run_full_filename,
@@ -230,6 +230,19 @@ def post_process_benchmark_results(
230230
)
231231
with open(local_benchmark_output_filename, "w") as json_file:
232232
json.dump(results_dict, json_file, indent=True)
233+
if benchmark_tool == "ycsb":
234+
logging.info(
235+
"Converting ycsb output to json. Storing it in: {}".format(
236+
local_benchmark_output_filename
237+
)
238+
)
239+
results_dict = post_process_ycsb_results(
240+
stdout.decode("ascii"),
241+
start_time_ms,
242+
start_time_str,
243+
)
244+
with open(local_benchmark_output_filename, "w") as json_file:
245+
json.dump(results_dict, json_file, indent=True)
233246

234247

235248
def check_benchmark_binaries_local_requirements(
@@ -242,6 +255,7 @@ def check_benchmark_binaries_local_requirements(
242255
benchmark_min_tool_version_patch,
243256
benchmark_tool,
244257
tool_source,
258+
tool_source_bin_path,
245259
) = extract_benchmark_tool_settings(benchmark_config)
246260
which_benchmark_tool = None
247261
if benchmark_tool is not None:
@@ -255,57 +269,17 @@ def check_benchmark_binaries_local_requirements(
255269
logging.info("Checking benchmark tool {} is accessible".format(benchmark_tool))
256270
which_benchmark_tool = shutil.which(benchmark_tool)
257271
if which_benchmark_tool is None:
258-
if tool_source is not None:
259-
logging.info(
260-
"Tool {} was not detected on path. Using remote source to retrieve it: {}".format(
261-
benchmark_tool, tool_source
262-
)
263-
)
264-
if tool_source.startswith("http"):
265-
if not os.path.isdir(binaries_localtemp_dir):
266-
os.mkdir(binaries_localtemp_dir)
267-
filename = tool_source.split("/")[-1]
268-
full_path = "{}/{}".format(binaries_localtemp_dir, filename)
269-
if not os.path.exists(full_path):
270-
logging.info(
271-
"Retrieving remote file from {} to {}. Using the dir {} as a cache for next time.".format(
272-
tool_source, full_path, binaries_localtemp_dir
273-
)
274-
)
275-
wget.download(tool_source, full_path)
276-
logging.info(
277-
"Decompressing {} into {}.".format(
278-
full_path, binaries_localtemp_dir
279-
)
280-
)
281-
if not os.path.exists(get_decompressed_filename(full_path)):
282-
full_path = decompress_file(full_path, binaries_localtemp_dir)
283-
else:
284-
full_path = get_decompressed_filename(full_path)
285-
benchmark_tool_workdir = os.path.abspath(full_path)
286-
executable = stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH
287-
which_benchmark_tool = which_local(
288-
benchmark_tool, executable, full_path, which_benchmark_tool
289-
)
290-
if which_benchmark_tool is None:
291-
raise Exception(
292-
"Benchmark tool {} was not acessible at {}. Aborting...".format(
293-
benchmark_tool, full_path
294-
)
295-
)
296-
else:
297-
logging.info(
298-
"Reusing cached remote file (located at {} ).".format(
299-
full_path
300-
)
301-
)
302-
303-
else:
304-
raise Exception(
305-
"Benchmark tool {} was not acessible. Aborting...".format(
306-
benchmark_tool
307-
)
308-
)
272+
(
273+
benchmark_tool_workdir,
274+
which_benchmark_tool,
275+
) = fetch_benchmark_tool_from_source_to_local(
276+
benchmark_tool,
277+
benchmark_tool_workdir,
278+
binaries_localtemp_dir,
279+
tool_source,
280+
tool_source_bin_path,
281+
which_benchmark_tool,
282+
)
309283
else:
310284
logging.info(
311285
"Tool {} was detected at {}".format(
@@ -332,6 +306,61 @@ def check_benchmark_binaries_local_requirements(
332306
return benchmark_tool, which_benchmark_tool, benchmark_tool_workdir
333307

334308

309+
def fetch_benchmark_tool_from_source_to_local(
310+
benchmark_tool,
311+
benchmark_tool_workdir,
312+
binaries_localtemp_dir,
313+
tool_source,
314+
bin_path,
315+
which_benchmark_tool,
316+
):
317+
if tool_source is not None and bin_path is not None:
318+
logging.info(
319+
"Tool {} was not detected on path. Using remote source to retrieve it: {}".format(
320+
benchmark_tool, tool_source
321+
)
322+
)
323+
if tool_source.startswith("http"):
324+
if not os.path.isdir(binaries_localtemp_dir):
325+
os.mkdir(binaries_localtemp_dir)
326+
filename = tool_source.split("/")[-1]
327+
full_path = "{}/{}".format(binaries_localtemp_dir, filename)
328+
if not os.path.exists(full_path):
329+
logging.info(
330+
"Retrieving remote file from {} to {}. Using the dir {} as a cache for next time.".format(
331+
tool_source, full_path, binaries_localtemp_dir
332+
)
333+
)
334+
wget.download(tool_source, full_path)
335+
logging.info(
336+
"Decompressing {} into {}.".format(full_path, binaries_localtemp_dir)
337+
)
338+
if not os.path.exists(get_decompressed_filename(full_path)):
339+
full_path = decompress_file(full_path, binaries_localtemp_dir)
340+
else:
341+
full_path = get_decompressed_filename(full_path)
342+
benchmark_tool_workdir = os.path.abspath(full_path)
343+
which_benchmark_tool = os.path.abspath(
344+
"{}/{}".format(benchmark_tool_workdir, bin_path)
345+
)
346+
if which_benchmark_tool is None:
347+
raise Exception(
348+
"Benchmark tool {} was not acessible at {}. Aborting...".format(
349+
benchmark_tool, full_path
350+
)
351+
)
352+
else:
353+
logging.info(
354+
"Reusing cached remote file (located at {} ).".format(full_path)
355+
)
356+
357+
else:
358+
raise Exception(
359+
"Benchmark tool {} was not acessible. Aborting...".format(benchmark_tool)
360+
)
361+
return benchmark_tool_workdir, which_benchmark_tool
362+
363+
335364
def which_local(benchmark_tool, executable, full_path, which_benchmark_tool):
336365
if which_benchmark_tool:
337366
return which_benchmark_tool

redisbench_admin/run_remote/args.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def create_run_remote_arguments(parser):
1313
parser.add_argument(
1414
"--allowed-tools",
1515
type=str,
16-
default="redis-benchmark,redisgraph-benchmark-go",
16+
default="redis-benchmark,redisgraph-benchmark-go,ycsb",
1717
help="comma separated list of allowed tools for this module. By default all the supported are allowed.",
1818
)
1919
parser.add_argument(

0 commit comments

Comments
 (0)