summaryrefslogtreecommitdiff
path: root/util/stats/output.py
diff options
context:
space:
mode:
Diffstat (limited to 'util/stats/output.py')
-rw-r--r--util/stats/output.py182
1 files changed, 182 insertions, 0 deletions
diff --git a/util/stats/output.py b/util/stats/output.py
new file mode 100644
index 000000000..44dba5d15
--- /dev/null
+++ b/util/stats/output.py
@@ -0,0 +1,182 @@
+# Copyright (c) 2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+class dbinfo(object):
+ def get(self, job, stat):
+ import info
+
+ run = info.source.allRunNames.get(job.name, None)
+ if run is None:
+ print 'run "%s" not found' % job
+ return None
+
+ stat.system = info.source[job.system]
+ info.display_run = run.run;
+ val = float(stat)
+ if val == 1e300*1e300:
+ return None
+ return val
+
+class StatOutput(object):
+ def __init__(self, name, jobfile, stat=None, info=dbinfo(), binstats=None):
+ self.name = name
+ self.jobfile = jobfile
+ self.stat = stat
+ self.binstats = None
+ self.label = self.name
+ self.invert = False
+ self.info = info
+
+ def printdata(self, bin = None, printmode = 'G'):
+ import info
+
+ if bin:
+ print '%s %s stats' % (self.name, bin)
+
+ if self.binstats:
+ for stat in self.binstats:
+ stat.bins = bin
+
+ if printmode == 'G':
+ valformat = '%g'
+ elif printmode != 'F' and value > 1e6:
+ valformat = '%0.5e'
+ else:
+ valformat = '%f'
+
+ for job in self.jobfile.jobs():
+ value = self.info.get(job, self.stat)
+ if value is None:
+ return
+
+ if not isinstance(value, list):
+ value = [ value ]
+
+ if self.invert:
+ for i,val in enumerate(value):
+ if val != 0.0:
+ value[i] = 1 / val
+
+ valstring = ', '.join([ valformat % val for val in value ])
+ print '%-50s %s' % (job.name + ':', valstring)
+
+ def display(self, binned = False, printmode = 'G'):
+ if binned and self.binstats:
+ self.printdata('kernel', printmode)
+ self.printdata('idle', printmode)
+ self.printdata('user', printmode)
+ self.printdata('interrupt', printmode)
+
+ print '%s total stats' % self.name
+ self.printdata(printmode=printmode)
+
+ def graph(self, graphdir):
+ from os.path import expanduser, join as joinpath
+ from barchart import BarChart
+ from matplotlib.numerix import Float, zeros
+ import re
+
+ confgroups = self.jobfile.groups()
+ ngroups = len(confgroups)
+ skiplist = [ False ] * ngroups
+ groupopts = None
+ baropts = None
+ groups = []
+ for i,group in enumerate(confgroups):
+ if group.flags.graph_group:
+ if groupopts is not None:
+ raise AttributeError, \
+ 'Two groups selected for graph group'
+ groupopts = group.subopts()
+ skiplist[i] = True
+ elif group.flags.graph_bars:
+ if baropts is not None:
+ raise AttributeError, \
+ 'Two groups selected for graph bars'
+ baropts = group.subopts()
+ skiplist[i] = True
+ else:
+ groups.append(group)
+
+ if groupopts is None:
+ raise AttributeError, 'No group selected for graph group'
+
+ if baropts is None:
+ raise AttributeError, 'No group selected for graph bars'
+
+ directory = expanduser(graphdir)
+ html = file(joinpath(directory, '%s.html' % self.name), 'w')
+ print >>html, '<html>'
+ print >>html, '<title>Graphs for %s</title>' % self.name
+ print >>html, '<body>'
+
+ for options in self.jobfile.options(groups):
+ data = zeros((len(groupopts), len(baropts)), Float)
+ data = [ [ None ] * len(baropts) for i in xrange(len(groupopts)) ]
+ enabled = False
+ stacked = None
+ for g,gopt in enumerate(groupopts):
+ for b,bopt in enumerate(baropts):
+ job = self.jobfile.job(options + [ gopt, bopt ])
+
+ val = self.info.get(job, self.stat)
+ if val is None:
+ val = 0.0
+ curstacked = isinstance(val, (list, tuple))
+ if stacked is None:
+ stacked = curstacked
+ else:
+ if stacked != curstacked:
+ raise ValueError, "some stats stacked, some not"
+
+ data[g][b] = val
+
+ bar_descs = [ opt.desc for opt in baropts ]
+ group_descs = [ opt.desc for opt in groupopts ]
+ if stacked:
+ legend = self.info.rcategories
+ else:
+ legend = bar_descs
+
+ chart = BarChart(data=data, xlabel='Benchmark', ylabel=self.label,
+ legend=legend, xticks=group_descs)
+ chart.graph()
+
+ names = [ opt.name for opt in options ]
+ descs = [ opt.desc for opt in options ]
+
+ filename = '%s-%s.png' % (self.name, ':'.join(names))
+ desc = ' '.join(descs)
+ filepath = joinpath(directory, filename)
+ chart.savefig(filepath)
+ filename = re.sub(':', '%3A', filename)
+ print >>html, '''%s<br><img src="%s"><br>''' % (desc, filename)
+
+ print >>html, '</body>'
+ print >>html, '</html>'
+ html.close()