source: benchmark/plot.py@ 17c6edeb

ADT ast-experimental pthread-emulation
Last change on this file since 17c6edeb was 41a6a78, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

It was brought to my attention that I forgot to commit this file

  • Property mode set to 100755
File size: 7.5 KB
Line 
1#!/usr/bin/python3
2"""
3Python Script to plot values obtained by the rmit.py script
4Runs a R.I.P.L.
5
6./plot.py
7-t trials
8-o option:values
9"""
10
11import argparse
12import itertools
13import json
14import math
15import numpy
16import os
17import re
18import statistics
19import sys
20import time
21
22import matplotlib
23import matplotlib.pyplot as plt
24from matplotlib.ticker import EngFormatter, ScalarFormatter
25
26def fmtDur( duration ):
27 if duration :
28 hours, rem = divmod(duration, 3600)
29 minutes, rem = divmod(rem, 60)
30 seconds, millis = divmod(rem, 1)
31 return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000)
32 return " n/a"
33
34class Field:
35 def __init__(self, unit, _min, _log, _name=None, _factor=1.0):
36 self.unit = unit
37 self.min = _min
38 self.log = _log
39 self.name = _name
40 self.factor = _factor
41
42field_names = {
43 "ns per ops" : Field('ns' , 0, False),
44 "Number of processors" : Field('' , 1, "exact"),
45 "Ops per procs" : Field('Ops' , 0, False),
46 "Ops per threads" : Field('Ops' , 0, False),
47 "ns per ops/procs" : Field('' , 0, False, _name = "ns $\\times$ (Processor $/$ Total Ops)" ),
48 "Number of threads" : Field('' , 1, False),
49 "Total Operations(ops)" : Field('Ops' , 0, False),
50 "Ops/sec/procs" : Field('Ops' , 0, False),
51 "Total blocks" : Field('Blocks', 0, False),
52 "Ops per second" : Field('' , 0, False),
53 "Cycle size (# thrds)" : Field('thrd' , 1, False),
54 "Duration (ms)" : Field('ms' , 0, False),
55 "Target QPS" : Field('' , 0, False),
56 "Actual QPS" : Field('' , 0, False),
57 "Average Read Latency" : Field('s' , 0, False, _factor = 0.000001),
58 "Median Read Latency" : Field('s' , 0, True, _factor = 0.000001),
59 "Tail Read Latency" : Field('s' , 0, True, _factor = 0.000001),
60 "Average Update Latency": Field('s' , 0, True, _factor = 0.000001),
61 "Median Update Latency" : Field('s' , 0, True, _factor = 0.000001),
62 "Tail Update Latency" : Field('s' , 0, True, _factor = 0.000001),
63 "Update Ratio" : Field('%' , 0, False),
64 "Request Rate" : Field('req/s' , 0, False),
65 "Data Rate" : Field('b/s' , 0, False, _factor = 1000 * 1000, _name = "Response Throughput"),
66 "Errors" : Field('%' , 0, False),
67}
68
69def plot(in_data, x, y, options, prefix):
70 fig, ax = plt.subplots()
71 colors = itertools.cycle(['#006cb4','#0aa000','#ff6600','#8510a1','#0095e3','#fd8f00','#e30002','#8f00d6','#4b009a','#ffff00','#69df00','#fb0300','#b13f00'])
72 series = {} # scatter data for each individual data point
73 groups = {} # data points for x value
74
75 print("Preparing Data")
76
77 for entry in in_data:
78 name = entry[0]
79 if options.filter and not name.startswith(options.filter):
80 continue
81
82 if not name in series:
83 series[name] = {'x':[], 'y':[]}
84
85 if not name in groups:
86 groups[name] = {}
87
88 if x in entry[2] and y in entry[2]:
89 xval = entry[2][x]
90 yval = entry[2][y] * field_names[y].factor
91 series[name]['x'].append(xval)
92 series[name]['y'].append(yval)
93
94 if not xval in groups[name]:
95 groups[name][xval] = []
96
97 groups[name][xval].append(yval)
98
99 print("Preparing Lines")
100
101 lines = {} # lines from groups with min, max, median, etc.
102 for name, data in groups.items():
103 if not name in lines:
104 lines[name] = { 'x': [], 'min':[], 'max':[], 'med':[], 'avg':[] }
105
106 for xkey in sorted(data):
107 ys = data[xkey]
108 lines[name]['x'] .append(xkey)
109 lines[name]['min'].append(min(ys))
110 lines[name]['max'].append(max(ys))
111 lines[name]['med'].append(statistics.median(ys))
112 lines[name]['avg'].append(statistics.mean(ys))
113
114 print("Making Plots")
115
116 for name, data in sorted(series.items()):
117 _col = next(colors)
118 plt.scatter(data['x'], data['y'], color=_col, label=name[len(prefix):], marker='x')
119 plt.plot(lines[name]['x'], lines[name]['min'], '--', color=_col)
120 plt.plot(lines[name]['x'], lines[name]['max'], '--', color=_col)
121 plt.plot(lines[name]['x'], lines[name]['med'], '-', color=_col)
122
123 print("Calculating Extremums")
124
125 mx = max([max(s['x']) for s in series.values()])
126 my = max([max(s['y']) for s in series.values()])
127
128 print("Finishing Plots")
129
130 plt.ylabel(field_names[y].name if field_names[y].name else y)
131 # plt.xticks(range(1, math.ceil(mx) + 1))
132 plt.xlabel(field_names[x].name if field_names[x].name else x)
133 plt.grid(b = True)
134 ax.xaxis.set_major_formatter( EngFormatter(unit=field_names[x].unit) )
135 if options.logx:
136 ax.set_xscale('log')
137 elif field_names[x].log:
138 ax.set_xscale('log')
139 if field_names[x].log == "exact":
140 xvals = set()
141 for s in series.values():
142 xvals |= set(s['x'])
143 ax.set_xticks(sorted(xvals))
144 ax.get_xaxis().set_major_formatter(ScalarFormatter())
145 plt.xticks(rotation = 45)
146 else:
147 plt.xlim(field_names[x].min, mx + 0.25)
148
149 if options.logy:
150 ax.set_yscale('log')
151 elif field_names[y].log:
152 ax.set_yscale('log')
153 else:
154 plt.ylim(field_names[y].min, options.MaxY if options.MaxY else my*1.2)
155
156 ax.yaxis.set_major_formatter( EngFormatter(unit=field_names[y].unit) )
157
158 plt.legend(loc='upper left')
159
160 print("Results Ready")
161 start = time.time()
162 if options.out:
163 plt.savefig(options.out, bbox_inches='tight')
164 else:
165 plt.show()
166 end = time.time()
167 print("Took {}".format(fmtDur(end - start)))
168
169
170if __name__ == "__main__":
171 # ================================================================================
172 # parse command line arguments
173 parser = argparse.ArgumentParser(description='Python Script to draw R.M.I.T. results')
174 parser.add_argument('-f', '--file', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help="Input file")
175 parser.add_argument('-o', '--out', nargs='?', type=str, default=None, help="Output file")
176 parser.add_argument('-y', nargs='?', type=str, default="", help="Which field to use as the Y axis")
177 parser.add_argument('-x', nargs='?', type=str, default="", help="Which field to use as the X axis")
178 parser.add_argument('--logx', action='store_true', help="if set, makes the x-axis logscale")
179 parser.add_argument('--logy', action='store_true', help="if set, makes the y-axis logscale")
180 parser.add_argument('--MaxY', nargs='?', type=int, help="maximum value of the y-axis")
181 parser.add_argument('--filter', nargs='?', type=str, default="", help="if not empty, only print series that start with specified filter")
182
183 options = parser.parse_args()
184
185 # if not options.out:
186 # matplotlib.use('SVG')
187
188 # ================================================================================
189 # load data
190 try :
191 data = json.load(options.file)
192 except :
193 print('ERROR: could not read input', file=sys.stderr)
194 parser.print_help(sys.stderr)
195 sys.exit(1)
196
197 # ================================================================================
198 # identify the keys
199
200 series = set()
201 fields = set()
202
203 for entry in data:
204 series.add(entry[0])
205 for label in entry[2].keys():
206 fields.add(label)
207
208 # filter out the series if needed
209 if options.filter:
210 series = set(filter(lambda elem: elem.startswith(options.filter), series))
211
212 # find the common prefix on series for removal (only if no filter)
213 prefix = os.path.commonprefix(list(series))
214
215 if not options.out :
216 print(series)
217 print("fields: ", ' '.join(fields))
218
219 wantx = "Number of processors"
220 wanty = "ns per ops"
221
222 if options.x:
223 if options.x in field_names.keys():
224 wantx = options.x
225 else:
226 print("Could not find X key '{}', defaulting to '{}'".format(options.x, wantx))
227
228 if options.y:
229 if options.y in field_names.keys():
230 wanty = options.y
231 else:
232 print("Could not find Y key '{}', defaulting to '{}'".format(options.y, wanty))
233
234
235 plot(data, wantx, wanty, options, prefix)
Note: See TracBrowser for help on using the repository browser.