Skip to content

Commit 20824cf

Browse files
[add] Enabled perf-report artifact on PROFILE=1 (#140)
1 parent 4295afe commit 20824cf

File tree

2 files changed

+110
-25
lines changed

2 files changed

+110
-25
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.2.9"
3+
version = "0.2.10"
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"

redisbench_admin/profilers/perf.py

Lines changed: 109 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ def generate_record_command(self, pid, output, frequency=None):
103103
cmd += ["--freq", "{}".format(frequency)]
104104
return cmd
105105

106+
def generate_report_command(self, input, dso=None):
107+
cmd = [self.perf, "report"]
108+
if dso is not None:
109+
cmd += ["--dso", dso]
110+
cmd += [
111+
"--header",
112+
"--no-children",
113+
"--stdio",
114+
"-g",
115+
"none,1.0,caller,function",
116+
"--input",
117+
input,
118+
]
119+
return cmd
120+
106121
def start_profile(self, pid, output, frequency=99):
107122
"""
108123
@param pid: profile events on specified process id
@@ -274,32 +289,78 @@ def generate_outputs(self, use_case, **kwargs):
274289
outputs["Flame Graph"] = flame_graph_output
275290
result &= artifact_result
276291

277-
if self.pprof_bin is None:
278-
logging.error(
279-
"Unable to detect pprof. Some of the capabilities will be disabled"
280-
)
281-
else:
282-
logging.info("Generating pprof text output")
283-
pprof_text_output = self.output + ".pprof.txt"
284-
artifact_result, pprof_artifact_text_output = run_pprof(
285-
self.pprof_bin,
286-
PPROF_FORMAT_TEXT,
287-
pprof_text_output,
288-
binary,
289-
self.output,
292+
# save perf output
293+
if artifact_result is True:
294+
outputs["perf output"] = os.path.abspath(self.output)
295+
296+
# generate perf report --stdio report
297+
logging.info("Generating perf report text outputs")
298+
perf_report_output = self.output + ".perf-report.top-cpu.txt"
299+
300+
artifact_result, perf_report_artifact = self.run_perf_report(
301+
perf_report_output, None
302+
)
303+
304+
if artifact_result is True:
305+
outputs["perf report top self-cpu"] = perf_report_artifact
306+
result &= artifact_result
307+
308+
# generate perf report --stdio report
309+
logging.info(
310+
"Generating perf report text outputs only for dso {}".format(binary)
311+
)
312+
perf_report_output_dso = self.output + ".perf-report.top-cpu.dso.txt"
313+
314+
artifact_result, perf_report_artifact = self.run_perf_report(
315+
perf_report_output_dso, binary
316+
)
317+
318+
if artifact_result is True:
319+
outputs[
320+
"perf report top self-cpu (dso={})".format(binary)
321+
] = perf_report_artifact
322+
result &= artifact_result
323+
324+
if self.callgraph_mode == "dwarf":
325+
logging.warning(
326+
"Unable to use perf output collected with callgraph dwarf mode in pprof. Skipping artifacts generation."
290327
)
291-
result &= artifact_result
292-
293-
if artifact_result is True:
294-
outputs["Top entries in text form"] = pprof_artifact_text_output
295-
logging.info("Generating pprof png output")
296-
pprof_png_output = self.output + ".pprof.png"
297-
artifact_result, pprof_artifact_png_output = run_pprof(
298-
self.pprof_bin, PPROF_FORMAT_PNG, pprof_png_output, binary, self.output
328+
logging.warning(
329+
"Check https://github.com/google/perf_data_converter/issues/40."
299330
)
300-
if artifact_result is True:
301-
outputs["Output graph image in PNG format"] = pprof_artifact_png_output
302-
result &= artifact_result
331+
else:
332+
if self.pprof_bin is None:
333+
logging.error(
334+
"Unable to detect pprof. Some of the capabilities will be disabled"
335+
)
336+
else:
337+
logging.info("Generating pprof text output")
338+
pprof_text_output = self.output + ".pprof.txt"
339+
artifact_result, pprof_artifact_text_output = run_pprof(
340+
self.pprof_bin,
341+
PPROF_FORMAT_TEXT,
342+
pprof_text_output,
343+
binary,
344+
self.output,
345+
)
346+
result &= artifact_result
347+
348+
if artifact_result is True:
349+
outputs["Top entries in text form"] = pprof_artifact_text_output
350+
logging.info("Generating pprof png output")
351+
pprof_png_output = self.output + ".pprof.png"
352+
artifact_result, pprof_artifact_png_output = run_pprof(
353+
self.pprof_bin,
354+
PPROF_FORMAT_PNG,
355+
pprof_png_output,
356+
binary,
357+
self.output,
358+
)
359+
if artifact_result is True:
360+
outputs[
361+
"Output graph image in PNG format"
362+
] = pprof_artifact_png_output
363+
result &= artifact_result
303364

304365
return result, outputs
305366

@@ -344,3 +405,27 @@ def generate_flame_graph(self, title="Flame Graph", subtitle="", filename=None):
344405

345406
def get_collapsed_stacks(self):
346407
return self.collapsed_stacks
408+
409+
def run_perf_report(
410+
self,
411+
output,
412+
dso,
413+
):
414+
status = False
415+
result_artifact = None
416+
args = self.generate_report_command(self.output, dso)
417+
logging.info("Running {} report with args {}".format(self.perf, args))
418+
try:
419+
stdout, _ = subprocess.Popen(
420+
args=args, stdout=subprocess.PIPE
421+
).communicate()
422+
logging.debug(stdout)
423+
with open(output, "w") as outfile:
424+
outfile.write(stdout.decode())
425+
status = True
426+
result_artifact = os.path.abspath(output)
427+
except OSError as e:
428+
logging.error(
429+
"Unable to run {} report. Error {}".format(self.perf, e.__str__())
430+
)
431+
return status, result_artifact

0 commit comments

Comments
 (0)