source: benchmark/plot.py @ 741e22c

ADTast-experimentalpthread-emulation
Last change on this file since 741e22c was c0458be3, checked in by Thierry Delisle <tdelisle@…>, 22 months 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.