source: benchmark/plot.py@ d1c47c2

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since d1c47c2 was d1c47c2, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Improved plotting scripts to handle memcached results

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