-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplot.py
154 lines (136 loc) · 4.4 KB
/
plot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python
"""Script to visualize google-benchmark output"""
import argparse
import sys
import logging
import json
import pandas as pd
import matplotlib.pyplot as plt
import pathlib
logging.basicConfig(format="[%(levelname)s] %(message)s")
METRICS = [
"real_time",
"cpu_time",
"bytes_per_second",
"items_per_second",
"iterations",
]
TRANSFORMS = {"": lambda x: x, "inverse": lambda x: 1.0 / x}
def get_default_ylabel(args):
"""Compute default ylabel for commandline args"""
label = ""
if args.transform == "":
label = args.metric
else:
label = args.transform + "(" + args.metric + ")"
if args.relative_to is not None:
label += " relative to %s" % args.relative_to
return label
def parse_args():
"""Parse commandline arguments"""
parser = argparse.ArgumentParser(description="Visualize google-benchmark output")
parser.add_argument(
"-f",
metavar="FILE",
type=argparse.FileType("r"),
default=sys.stdin,
dest="file",
help="path to file containing the json benchmark data",
)
parser.add_argument(
"-m",
metavar="METRIC",
choices=METRICS,
default=METRICS[0],
dest="metric",
help="metric to plot on the y-axis, valid choices are: %s" % ", ".join(METRICS),
)
parser.add_argument(
"-t",
metavar="TRANSFORM",
choices=TRANSFORMS.keys(),
default="",
help="transform to apply to the chosen metric, valid choices are: %s"
% ", ".join(list(TRANSFORMS)),
dest="transform",
)
parser.add_argument(
"-r",
metavar="RELATIVE_TO",
type=str,
default=None,
dest="relative_to",
help="plot metrics relative to this label",
)
parser.add_argument(
"--xlabel", type=str, default="input size", help="label of the x-axis"
)
parser.add_argument("--ylabel", type=str, help="label of the y-axis")
parser.add_argument("--title", type=str, default="", help="title of the plot")
parser.add_argument(
"--logx", action="store_true", help="plot x-axis on a logarithmic scale"
)
parser.add_argument(
"--logy", action="store_true", help="plot y-axis on a logarithmic scale"
)
parser.add_argument(
"--output", type=str, default="", help="File in which to save the graph"
)
args = parser.parse_args()
if args.ylabel is None:
args.ylabel = get_default_ylabel(args)
return args
def parse_input_size(name):
splits = name.split("/")
if len(splits) == 1:
return 1
return int(splits[1])
def read_data(args):
"""Read and process dataframe using commandline args"""
try:
json_data = json.load(args.file)
data = pd.DataFrame(json_data["benchmarks"])
except ValueError:
logging.error('Could not parse the benchmark data. Did you forget "--benchmark_format=json when running the benchmark"?')
exit(1)
data["label"] = data["name"].apply(lambda x: x.split("/")[0])
data["input"] = data["name"].apply(parse_input_size)
data[args.metric] = data[args.metric].apply(TRANSFORMS[args.transform])
return data
def plot_groups(label_groups, args):
"""Display the processed data"""
for label, group in label_groups.items():
plt.plot(group["input"], group[args.metric], label=label, marker=".")
if args.logx:
plt.xscale("log", base=2)
if args.logy:
plt.yscale("log")
plt.xlabel(args.xlabel)
plt.ylabel(args.ylabel)
plt.title(args.title)
plt.legend()
if args.output:
logging.info("Saving to %s" % args.output)
plt.savefig(args.output)
else:
plt.show()
def main():
"""Entry point of the program"""
args = parse_args()
data = read_data(args)
label_groups = {}
for label, group in data.groupby("label"):
label_groups[label] = group.set_index("input", drop=False)
if args.relative_to is not None:
try:
baseline = label_groups[args.relative_to][args.metric].copy()
except KeyError as key:
msg = "Key %s is not present in the benchmark output"
logging.error(msg, str(key))
exit(1)
if args.relative_to is not None:
for label in label_groups:
label_groups[label][args.metric] /= baseline
plot_groups(label_groups, args)
if __name__ == "__main__":
main()