Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • benchmark/plot.py

    rf34f95c re9c5db2  
    1515import numpy
    1616import re
     17import statistics
    1718import sys
    1819
     
    2122
    2223class Field:
    23         def __init__(self, unit, _min):
     24        def __init__(self, unit, _min, _log):
    2425                self.unit = unit
    2526                self.min  = _min
     27                self.log  = _log
    2628
    2729field_names = {
    28         "ns per ops"           : Field('ns'    , 0),
    29         "Number of processors" : Field(''      , 1),
    30         "Ops per procs"        : Field('Ops'   , 0),
    31         "Ops per threads"      : Field('Ops'   , 0),
    32         "ns per ops/procs"     : Field('ns'    , 0),
    33         "Number of threads"    : Field('thrd'  , 1),
    34         "Total Operations(ops)": Field('Ops'   , 0),
    35         "Ops/sec/procs"        : Field('Ops'   , 0),
    36         "Total blocks"         : Field('Blocks', 0),
    37         "Ops per second"       : Field('Ops'   , 0),
    38         "Cycle size (# thrds)" : Field('thrd'  , 1),
    39         "Duration (ms)"        : Field('ms'    , 0),
     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),
    4048}
    4149
    42 def plot(data, x, y, out):
     50def plot(in_data, x, y, out):
    4351        fig, ax = plt.subplots()
    4452        colors = itertools.cycle(['#0095e3','#006cb4','#69df00','#0aa000','#fb0300','#e30002','#fd8f00','#ff7f00','#8f00d6','#4b009a','#ffff00','#b13f00'])
    45         series = {}
    46         for entry in data:
    47                 if not entry[0] in series:
    48                         series[entry[0]] = {'x':[], 'y':[]}
     53        series = {} # scatter data for each individual data point
     54        groups = {} # data points for x value
     55
     56        print("Preparing Data")
     57
     58        for entry in in_data:
     59                name = entry[0]
     60                if not name in series:
     61                        series[name] = {'x':[], 'y':[]}
     62
     63                if not name in groups:
     64                        groups[name] = {}
    4965
    5066                if x in entry[2] and y in entry[2]:
    51                         series[entry[0]]['x'].append(entry[2][x])
    52                         series[entry[0]]['y'].append(entry[2][y])
     67                        xval = entry[2][x]
     68                        yval = entry[2][y]
     69                        series[name]['x'].append(xval)
     70                        series[name]['y'].append(yval)
     71
     72                        if not xval in groups[name]:
     73                                groups[name][xval] = []
     74
     75                        groups[name][xval].append(yval)
     76
     77        print("Preparing Lines")
     78
     79        lines = {} # lines from groups with min, max, median, etc.
     80        for name, data in groups.items():
     81                if not name in lines:
     82                        lines[name] = { 'x': [], 'min':[], 'max':[], 'med':[], 'avg':[] }
     83
     84                for xkey in sorted(data):
     85                        ys = data[xkey]
     86                        lines[name]['x']  .append(xkey)
     87                        lines[name]['min'].append(min(ys))
     88                        lines[name]['max'].append(max(ys))
     89                        lines[name]['med'].append(statistics.median(ys))
     90                        lines[name]['avg'].append(statistics.mean(ys))
     91
     92        print("Making Plots")
    5393
    5494        for name, data in series.items():
    55                 plt.scatter(data['x'], data['y'], color=next(colors), label=name, marker='x')
     95                _col = next(colors)
     96                plt.scatter(data['x'], data['y'], color=_col, label=name, marker='x')
     97                plt.plot(lines[name]['x'], lines[name]['min'], '--', color=_col)
     98                plt.plot(lines[name]['x'], lines[name]['max'], '--', color=_col)
     99                plt.plot(lines[name]['x'], lines[name]['med'], '-', color=_col)
     100
     101        print("Calculating Extremums")
    56102
    57103        mx = max([max(s['x']) for s in series.values()])
    58104        my = max([max(s['y']) for s in series.values()])
    59105
     106        print("Finishing Plots")
     107
    60108        plt.ylabel(y)
    61         plt.xlim(field_names[x].min, mx + 0.25)
    62         plt.xticks(range(1, math.ceil(mx) + 1))
     109        # plt.xticks(range(1, math.ceil(mx) + 1))
    63110        plt.xlabel(x)
    64         plt.ylim(field_names[y].min, my*1.2)
    65111        plt.grid(b = True)
    66112        ax.xaxis.set_major_formatter( EngFormatter(unit=field_names[x].unit) )
     113        if field_names[x].log:
     114                ax.set_xscale('log')
     115        else:
     116                plt.xlim(field_names[x].min, mx + 0.25)
     117
    67118        ax.yaxis.set_major_formatter( EngFormatter(unit=field_names[y].unit) )
     119        if field_names[y].log:
     120                ax.set_yscale('log')
     121        else:
     122                plt.ylim(field_names[y].min, my*1.2)
     123
    68124        plt.legend(loc='upper left')
     125
     126        print("Results Ready")
    69127        if out:
    70128                plt.savefig(out)
     
    76134        # ================================================================================
    77135        # parse command line arguments
    78         parser = parser = argparse.ArgumentParser(description='Python Script to draw R.M.I.T. results')
    79         parser.add_argument('-f', '--file', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
    80         parser.add_argument('-o', '--out', nargs='?', type=str, default=None)
    81         parser.add_argument('-y', nargs='?', type=str, default="")
     136        parser = argparse.ArgumentParser(description='Python Script to draw R.M.I.T. results')
     137        parser.add_argument('-f', '--file', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help="Input file")
     138        parser.add_argument('-o', '--out', nargs='?', type=str, default=None, help="Output file")
     139        parser.add_argument('-y', nargs='?', type=str, default="", help="Which field to use as the Y axis")
     140        parser.add_argument('-x', nargs='?', type=str, default="", help="Which field to use as the X axis")
    82141
    83         try:
    84                 options =  parser.parse_args()
    85         except:
    86                 print('ERROR: invalid arguments', file=sys.stderr)
    87                 parser.print_help(sys.stderr)
    88                 sys.exit(1)
     142        options =  parser.parse_args()
    89143
    90144        # ================================================================================
     
    110164        if not options.out :
    111165                print(series)
    112                 print("fields")
    113                 for f in fields:
    114                         print("{}".format(f))
     166                print("fields: ", ' '.join(fields))
    115167
    116         if options.y and options.y in field_names.keys():
    117                 plot(data, "Number of processors", options.y, options.out)
    118         else:
    119                 if options.y:
    120                         print("Could not find key '{}', defaulting to 'ns per ops'".format(options.y))
    121                 plot(data, "Number of processors", "ns per ops", options.out)
     168        wantx = "Number of processors"
     169        wanty = "ns per ops"
     170
     171        if options.x:
     172                if options.x in field_names.keys():
     173                        wantx = options.x
     174                else:
     175                        print("Could not find X key '{}', defaulting to '{}'".format(options.x, wantx))
     176
     177        if options.y:
     178                if options.y in field_names.keys():
     179                        wanty = options.y
     180                else:
     181                        print("Could not find Y key '{}', defaulting to '{}'".format(options.y, wanty))
     182
     183
     184        plot(data, wantx, wanty, options.out)
Note: See TracChangeset for help on using the changeset viewer.