Commit 66faf965 authored by Florian Fischer's avatar Florian Fischer
Browse files

improve plot_tail_latency

* add output file support.
* create multiple plots at once.
* use less extreme percentiles
parent c95d306f
......@@ -45,7 +45,7 @@ def get_bar_data(latency_files, latency='total', include_raw_data=False):
return data
def plot_tail_latency_bar_tikz(latency_files, latency):
def plot_tail_latency_bar_tikz(latency_files, latency, out=None):
preamble = Template("""\\documentclass{standalone}
\\input{common.tex}
......@@ -63,7 +63,7 @@ def plot_tail_latency_bar_tikz(latency_files, latency):
ylabel={latency in ms},
xlabel={percentiles},
cycle list name=barvibrant,
symbolic x coords={50\\%,95\\%,99\\%,99.9\\%,99.99\\%},
symbolic x coords={50\\%,95\\%,99\\%,99.9\\%},
xtick=data,
nodes near coords,
nodes near coords align={horizontal},
......@@ -74,7 +74,7 @@ def plot_tail_latency_bar_tikz(latency_files, latency):
]
""")
addplot = "\\addplot coordinates {{(50\\%, {p50:.2f}) (95\\%, {p95:.2f}) (99\\%, {p99:.2f}) (99.9\\%, {p99_9:.2f}) (99.99\\%, {p99_99:.2f})}};"
addplot = "\\addplot coordinates {{(50\\%, {p50:.2f}) (95\\%, {p95:.2f}) (99\\%, {p99:.2f}) (99.9\\%, {p99_9:.2f})}};"
tail = Template("""\\legend{$labels}
\\end{axis}
......@@ -88,28 +88,35 @@ def plot_tail_latency_bar_tikz(latency_files, latency):
impl_label = plot_utils.subst_runtime_name(impl)
labels += f'{impl_label}, '
# convert to ms
p50, p95, p99, p99_9, p99_99 = np.array([
p50, p95, p99, p99_9 = np.array([
data['median'],
data[95],
data[99],
data[99.9],
data[99.99],
]) / 1000000
plots.append(
addplot.format(p50=p50,
p95=p95,
p99=p99,
p99_9=p99_9,
p99_99=p99_99))
plots.append(addplot.format(p50=p50, p95=p95, p99=p99, p99_9=p99_9))
print(preamble.substitute(latency_files=latency_files))
tex = f'{preamble.substitute(latency_files=latency_files)}\n'
for plot in plots:
print(plot)
print(tail.substitute(labels=labels[:-2]))
tex = f'{tex}\n{plot}'
tex = f'{tex}\n{tail.substitute(labels=labels[:-2])}'
if out is None:
print(tex)
else:
with open(out, 'w', encoding='utf-8') as out_file:
print(tex, file=out_file)
def plot_tail_latency_bar(latency_files, latency):
def pyplot_show_or_save(out=None):
if out is None:
plt.show()
else:
plt.savefig(out)
def plot_tail_latency_bar(latency_files, latency, out=None):
n_impls = len(latency_files)
width = 1 / (n_impls + 1)
......@@ -117,15 +124,12 @@ def plot_tail_latency_bar(latency_files, latency):
for i, (impl, data) in enumerate(
get_bar_data(latency_files, latency=latency).items()):
x_base = np.arange(1, len(data) + 1)
x_base = np.arange(1, len(data))
x = x_base + width / 2 + (i * width)
y = np.array([
data['mean'], data['median'], data[95], data[99], data[99.99],
data[99.999]
])
y = np.array(
[data['mean'], data['median'], data[95], data[99], data[99.9]])
# convert to ms
y = y / 1000000
print(x, y)
impl_label = plot_utils.subst_runtime_name(impl)
impl_bars.append(plt.bar(x, y, label=impl_label, width=width))
......@@ -143,13 +147,13 @@ def plot_tail_latency_bar(latency_files, latency):
plt.ylabel(f'{latency} latency in ms')
plt.xlabel('percentiles')
plt.xticks(x_base + (n_impls / 2 * width),
['mean', 'median', '95%', '99%', '99.99%', '99.999%'])
['mean', 'median', '95%', '99%', '99.9%'])
plt.legend()
plt.show()
pyplot_show_or_save(out=out)
def plot_tail_latency_linear(latency_files, latency):
field = CSV_FIELDS[args.latency]
def plot_tail_latency_linear(latency_files, latency, out=None):
field = CSV_FIELDS[latency]
for latency_file in latency_files:
path = pathlib.Path(latency_file)
ns = np.sort(
......@@ -168,8 +172,9 @@ def plot_tail_latency_linear(latency_files, latency):
plt.xticks([0, in_data // 2, in_data], ['90%', '95%', '100%'])
plt.ylabel(f'{latency} latency in ms')
plt.ylim((0, 2000))
plt.legend()
plt.show()
pyplot_show_or_save(out=out)
def summarize(latency_files, latency):
......@@ -214,16 +219,18 @@ def summarize(latency_files, latency):
print(f'{name}-hist-bin-edges: {[f"{e:.2f}" for e in bin_edges]}')
if __name__ == '__main__':
def main():
parser = argparse.ArgumentParser()
parser.add_argument("data_files", nargs='+')
parser.add_argument("--latency",
choices=['total', 'after-send', 'after-send-dispatch'],
default='total')
parser.add_argument("--plot",
parser.add_argument("--plots",
choices=['line', 'bar', 'bar-tikz'],
default='line')
nargs='+',
default=['line'])
parser.add_argument("--summarize", action='store_true')
parser.add_argument("--out", type=str, nargs='*', help='Output files')
args = parser.parse_args()
......@@ -231,9 +238,16 @@ if __name__ == '__main__':
summarize(args.data_files, args.latency)
sys.exit(0)
if args.plot == 'bar':
plot_tail_latency_bar(args.data_files, args.latency)
elif args.plot == 'line':
plot_tail_latency_linear(args.data_files, args.latency)
else:
plot_tail_latency_bar_tikz(args.data_files, args.latency)
plots = {
'bar': plot_tail_latency_bar,
'line': plot_tail_latency_linear,
'bar-tikz': plot_tail_latency_bar_tikz
}
for i, plot in enumerate(args.plots):
out = args.out[i] if args.out and i < len(args.out) else None
plots[plot](args.data_files, args.latency, out=out)
if __name__ == '__main__':
main()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment