#!/usr/bin/env python import defapp from os.path import splitext, basename from optparse import make_option as o from tempfile import NamedTemporaryFile as Tmp from gnuplot import gnuplot, FORMATS options = [ o(None, '--shared-l3', action='store_true', dest='sharedL3'), o('-f', '--format', action='store', dest='format', type='choice', choices=FORMATS, help='output format'), o(None, '--paper', action='store_true', dest='paper'), o(None, '--wide', action='store_true', dest='wide'), ] defaults = { 'sharedL3' : False, 'format' : 'show', 'xrange' : (49.5, 250.5), 'yrange' : (0, 500.05), 'xticks' : (0, 10), 'yticks' : (0, 50), 'title' : None, 'xlabel' : 'number of tasks', 'ylabel' : 'overhead (us)', 'paper' : False, 'split' : False, 'wide' : False, } def decode(name): params = {} parts = name.split('_') for p in parts: kv = p.split('=') k = kv[0] v = kv[1] if len(kv) > 1 else None params[k] = v return params def get_data_tmpfile(datafile): """Removes all comments form datafile, stores result in a temp file. The temp file is returned.""" count = 0 f = open(datafile, 'r') d = Tmp() for line in f: if len(line) > 1 and line[0] != '#': d.write(line) count += 1 f.close() d.flush() if count > 0: return d else: del d # removes temp file return None def scenario_heading(conf, want_period=False, sharedL3=False): ovd_type = 'unknowkn overhead' if 'ovd' in conf: if conf['ovd'] == 'preemption': ovd_type = 'Preemption ovhead' elif conf['ovd'] == 'onchip': if sharedL3: ovd_type = 'Shared L3 migration ovhead' else: ovd_type = 'Shared L2 migration ovhead' elif conf['ovd'] == 'l2cache': ovd_type = 'Shared L2 migration ovhead' elif conf['ovd'] == 'offchip': ovd_type = 'Off Chip migration ovhead' dist = 'unknown distribution' if 'dist' in conf: if conf['dist'] == 'uni': dist = 'utilization uniformly ' if 'light' in conf: dist = dist + 'in [0.001, 0.1]' elif 'medium' in conf: dist = dist + 'in [0.1, 0.4]' elif 'heavy' in conf: dist = dist + 'in [0.5, 0.9]' elif conf['dist'] == 'bimo': dist = 'util. bimodially ' if 'light' in conf: dist = dist + 'in [0.001, 0.5] (8/9) and [0.5, 0.9] (1/9)' elif 'medium' in conf: dist = dist + 'in [0.001, 0.5] (6/9) and [0.5, 0.9] (3/9)' elif 'heavy' in conf: dist = dist + 'in [0.001, 0.5] (4/9) and [0.5, 0.9] (5/9)' if want_period: if '33' in conf: dist += '; period uniformly in [3, 33]' elif '250' in conf: dist += '; period uniformly in [50, 250]' else: dist += '; period uniformly in [10, 100]' return ovd_type + '; ' + dist class PmPlotter(defapp.App): def __init__(self): defapp.App.__init__(self, options, defaults, no_std_opts=True) def plot(self, graphs, title, name, conf, **xtra): gnuplot(graphs, title=title, xlabel=self.options.xlabel, ylabel=self.options.ylabel + (' [avg]' if 'soft' in conf else ' [max]'), xrange=self.options.xrange, yrange=self.options.yrange, xticks=self.options.xticks, yticks=self.options.yticks, format=self.options.format, fname=name, **xtra) def plot_wide(self, graphs, title, name, conf, **xtra): tops = 'rounded size 16cm,6.5cm' gnuplot(graphs, title=title, xlabel=self.options.xlabel, ylabel=self.options.ylabel + (' [avg]' if 'soft' in conf else ' [max]'), xrange=self.options.xrange, yrange=self.options.yrange, xticks=self.options.xticks, yticks=self.options.yticks, format=self.options.format, fname=name, term_opts=tops, **xtra) def plot_paper(self, graphs, title, name, conf, **xtra): tops = 'color solid font "Helvetica,10" linewidth 1.0 rounded size 16cm,8.5cm' gnuplot(graphs, title=title, xlabel=self.options.xlabel, ylabel=self.options.ylabel + (' [avg]' if 'soft' in conf else ' [max]'), xrange=self.options.xrange, yrange=self.options.yrange, xticks=self.options.xticks, yticks=self.options.yticks, format=self.options.format, fname=name, key='off', style='lines lw 7', term_opts=tops) def plot_pm(self, tmpfile, name, conf): title = scenario_heading(conf, want_period=True, sharedL3=self.options.sharedL3) plugin = conf['plugin'] wsslist = conf['wss'].split(',') graphs = [] wsspos = 2 for i in wsslist: if 'soft' in conf: wsspos += 1 label = plugin + ' WSS=' + i graphs.append((tmpfile, 1, wsspos, label)) wsspos += 2 if self.options.paper and self.options.format == 'pdf': self.plot_paper(graphs, title, name, conf) elif self.options.wide and self.options.format == 'pdf': self.plot_wide(graphs, title, name, conf) else: self.plot(graphs, title, name, conf) def plot_file(self, datafile): bname = basename(datafile) name, ext = splitext(bname) if ext != '.csv': self.err("Warning: '%s' doesn't look like a CSV file." % bname) conf = decode(name) tmpfile = get_data_tmpfile(datafile) if tmpfile: if 'pm' in conf: self.plot_pm(tmpfile.name, name, conf) else: self.err("Skipped '%s'; unkown experiment type." % bname) del tmpfile # removes temp file else: self.err("Skipped '%s'; it dosn't appear to contain data." % bname) def default(self, _): for datafile in self.args: self.plot_file(datafile) if __name__ == "__main__": PmPlotter().launch()