source: benchmark/plot.py@ 80d16f8

ADT ast-experimental pthread-emulation
Last change on this file since 80d16f8 was c0458be3, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

More small changes to the plot script and added script to parse trun results.

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