memgraph/tools/plot_ldbc_latency
Matej Ferencevic 686dc452ee LDBC: Integrate with Apollo
Summary:
Run neo4j and memgraph from run_benchmark script.
This makes mg and neo scripts obsolete.

Reviewers: buda, teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D806
2017-09-21 22:29:42 +02:00

179 lines
6.4 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
Latency Barchart (Based on LDBC JSON output).
'''
import json
import os
import numpy as np
from argparse import ArgumentParser
import string
import matplotlib
# Must set 'Agg' backend before importing pyplot
# This is so the script works on headless machines (without X11)
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
COLORS = ['#ff7300', '#008cc2'] # TODO: add more colors!
LDBC_TIME_FACTORS = {
"SECONDS": 1.0,
"MILLISECONDS": 1000.0,
"MICROSECONDS": 1000000.0,
"NANOSECONDS": 1000000000.0
}
TIME_FACTORS = {
"s": 1.0,
"ms": 1000,
"us": 1000000,
"ns": 1000000000,
}
def parse_args():
argp = ArgumentParser(description=__doc__)
argp.add_argument("--vendor-titles", nargs="+",
default=["Memgraph", "Market leader"],
help="Vender titles that are going to appear "
"on the plot, e.g. legend titles.")
argp.add_argument("--plot-title", default="",
help="Plot title.")
argp.add_argument("--logo-path", default=None,
help="Path to the logo that is going to be presented"
" instead of title.")
argp.add_argument("--results", nargs="+", required=True,
help="Path to the folder with result files in format "
"{{vendor-reference}}-LDBC-results.json")
argp.add_argument("--time-unit", choices=("s", "ms", "us", "ns"),
default="ms", help="The time unit that should be used.")
argp.add_argument("--output", default="",
help="Save plot to file (instead of displaying it).")
argp.add_argument("--max-label-width", default=11, type=int,
help="Maximum length of the x-axis labels (-1 is unlimited)")
return argp.parse_args()
def autolabel(ax, rects):
"""
Attach a text label above each bar displaying its height
"""
for rect in rects:
height = rect.get_height()
# TODO: adjust more vendors
ax.text(rect.get_x() + rect.get_width()/2., 1.00*height,
'%d' % int(height),
ha='center', va='bottom')
def main():
# Read the arguments.
args = parse_args()
# Prepare the datastructure.
vendors = []
for i, results_file, vendor_title in zip(range(len(args.results)),
args.results,
args.vendor_titles):
vendor = {}
vendor['title'] = vendor_title
vendor['results_file'] = results_file
vendor['color'] = COLORS[i]
vendor['results'] = []
vendors.append(vendor)
assert len(vendors) == 2, "The graph is tailored for only 2 vendors."
# Collect the benchmark data.
print("LDBC Latency Data")
for vendor in vendors:
with open(vendor['results_file']) as results_file:
results_data = json.load(results_file)
for query_data in results_data["all_metrics"]:
mean_runtime = (query_data["run_time"]["mean"] /
LDBC_TIME_FACTORS[results_data["unit"]] *
TIME_FACTORS[args.time_unit])
query_name = query_data['name']
vendor['results'].append((query_name, mean_runtime))
# Sort results.
for vendor in vendors:
vendor['results'].sort(key=lambda item: int("".join(filter(
lambda x: x in string.digits, item[0]))))
# Print results.
for vendor in vendors:
print("Vendor:", vendor['title'])
for query_name, latency in vendor['results']:
print("{} -> {:.3f}{}".format(query_name, latency, args.time_unit))
# Consistency check.
all_query_names = [tuple(res[0] for res in vd['results']) for vd in vendors]
assert len(set(all_query_names)) == 1, \
"Queries between different vendors are different!"
query_names = all_query_names[0]
# Plot.
ind = np.arange(len(query_names)) # the x locations for the groups
width = 0.40 # the width of the bars
fig, ax = plt.subplots() # figure setup
fig.set_size_inches(1920 / 96, 1080 / 96) # set figure size
ax.set_ylabel('Mean Latency (%s)' % (args.time_unit)) # YAxis title
ax.set_facecolor('#dcdcdc') # plot bg color (light gray)
ax.set_xticks(ind + width / len(vendors)) # TODO: adjust (more vendors)
def shorten_query_name(query_name):
# Long query names on the x-axis don't look compelling.
if query_name.lower().startswith('ldbc'):
query_name = query_name[4:]
if len(query_name) > args.max_label_width:
query_name = query_name[:args.max_label_width] + '\N{HORIZONTAL ELLIPSIS}'
return query_name
labels = query_names
if args.max_label_width == 0:
labels = ["Q{}".format(i) for i, _ in enumerate(query_names)]
elif args.max_label_width > 0:
labels = map(shorten_query_name, query_names)
ax.set_xticklabels(labels, rotation=30)
# set only horizontal grid lines
for line in ax.get_xgridlines():
line.set_linestyle(' ')
for line in ax.get_ygridlines():
line.set_linestyle('--')
ax.set_axisbelow(True) # put the grid below all other elements
plt.grid(True) # show grid
# Set plot title
ax.set_title(args.plot_title)
# Draw logo or plot title
if args.logo_path != None:
# TODO: improve the logo positioning
im = plt.imread(get_sample_data(os.path.join(os.getcwd(),
args.logo_path)))
plt.gcf().subplots_adjust(top=0.85)
newax = fig.add_axes([0.46, 0.85, 0.12, 0.15], anchor='N')
newax.imshow(im)
newax.axis('off')
# Draw bars
for index, vendor in enumerate(vendors):
latencies = [res[1] for res in vendor['results']]
rects = ax.bar(ind + index * width, latencies, width,
color=vendor['color'])
vendor['rects'] = rects
autolabel(ax, rects)
rects = [vd['rects'][0] for vd in vendors]
titles = [vd['title'] for vd in vendors]
ax.legend(rects, titles) # Draw the legend.
if args.output == "":
plt.show()
else:
plt.savefig(args.output, dpi=96)
if __name__ == '__main__':
main()