#!/usr/bin/env python2 # Copyright (c) 2003-2004 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 import re, sys, math def usage(): print '''\ Usage: %s [-E] [-F] [ -G ] [-d ] [-g ] [-h ] [-p] [-s ] [-r ] [-T ] [-u ] [command args] commands extra parameters description ----------- ------------------ --------------------------------------- formula Evaluated formula specified formulas [regex] List formulas (only matching regex) runs none List all runs in database samples none List samples present in database stability Calculated statistical info about stats stat Show stat data (only matching regex) stats [regex] List all stats (only matching regex) database Where command is drop, init, or clean ''' % sys.argv[0] sys.exit(1) def getopts(list, flags): import getopt try: opts, args = getopt.getopt(list, flags) except getopt.GetoptError: usage() return opts, args class CommandException(Exception): pass def commands(options, command, args): if command == 'database': if len(args) == 0: raise CommandException import dbinit mydb = dbinit.MyDB(options) if args[0] == 'drop': if len(args) > 2: raise CommandException mydb.admin() mydb.drop() if len(args) == 2 and args[1] == 'init': mydb.create() mydb.connect() mydb.populate() mydb.close() return if args[0] == 'init': if len(args) > 1: raise CommandException mydb.admin() mydb.create() mydb.connect() mydb.populate() mydb.close() return if args[0] == 'clean': if len(args) > 1: raise CommandException mydb.connect() mydb.clean() return raise CommandException import db source = db.Database() source.host = options.host source.db = options.db source.passwd = options.passwd source.user = options.user source.connect() #source.update_dict(globals()) if type(options.method) is str: source.method = options.method if options.runs is None: runs = source.allRuns else: rx = re.compile(options.runs) runs = [] for run in source.allRuns: if rx.match(run.name): runs.append(run) if command == 'runs': user = None opts, args = getopts(args, '-u') if len(args): raise CommandException for o,a in opts: if o == '-u': user = a source.listRuns(user) return if command == 'stats': if len(args) == 0: source.listStats() elif len(args) == 1: source.listStats(args[0]) else: raise CommandException return if command == 'formulas': if len(args) == 0: source.listFormulas() elif len(args) == 1: source.listFormulas(args[0]) else: raise CommandException return if command == 'samples': if len(args): raise CommandException source.listTicks(runs) return if command == 'stability': if len(args) < 2: raise CommandException try: merge = int(args[0]) except ValueError: usage() stats = source.getStat(args[1]) source.method = 'sum' def disp(*args): print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args # temporary variable containing a bunch of dashes d = '-' * 100 #loop through all the stats selected for stat in stats: print "%s:" % stat.name disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", "SAMP", "CV") disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10]) #loop through all the selected runs for run in runs: runTicks = source.retTicks([ run ]) #throw away the first one, it's 0 runTicks.pop(0) source.ticks = runTicks avg = 0 stdev = 0 numoutsideavg = 0 numoutside1std = 0 numoutside2std = 0 pairRunTicks = [] if value(stat, run.run) == 1e300*1e300: continue for t in range(0, len(runTicks)-(merge-1), merge): tempPair = [] for p in range(0,merge): tempPair.append(runTicks[t+p]) pairRunTicks.append(tempPair) #loop through all the various ticks for each run for tick in pairRunTicks: source.ticks = tick avg += value(stat, run.run) avg /= len(pairRunTicks) for tick in pairRunTicks: source.ticks = tick val = value(stat, run.run) stdev += pow((val-avg),2) stdev = math.sqrt(stdev / len(pairRunTicks)) for tick in pairRunTicks: source.ticks = tick val = value(stat, run.run) if (val < (avg * .9)) or (val > (avg * 1.1)): numoutsideavg += 1 if (val < (avg - stdev)) or (val > (avg + stdev)): numoutside1std += 1 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))): numoutside2std += 1 if avg > 1000: disp(run.name, "%.1f" % avg, "%.1f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.3f" % (stdev/avg*100)) elif avg > 100: disp(run.name, "%.1f" % avg, "%.1f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.5f" % (stdev/avg*100)) else: disp(run.name, "%.5f" % avg, "%.5f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.7f" % (stdev/avg*100)) return if command == 'all': if len(args): raise CommandException all = [ 'bps', 'misses', 'mpkb', 'ipkb', 'pps', 'bpt' ] for command in all: commands(options, command, args) if options.ticks: if not options.graph: print 'only displaying sample %s' % options.ticks source.ticks = [ int(x) for x in options.ticks.split() ] from output import StatOutput output = StatOutput(options.jobfile, source) output.xlabel = 'System Configuration' output.colormap = 'RdYlGn' if command == 'stat' or command == 'formula': if len(args) != 1: raise CommandException if command == 'stat': stats = source.getStat(args[0]) if command == 'formula': stats = eval(args[0]) for stat in stats: output.stat = stat output.ylabel = stat.name if options.graph: output.graph(stat.name, options.graphdir) else: output.display(stat.name, options.printmode) return if len(args): raise CommandException from info import ProxyGroup proxy = ProxyGroup(system = source[options.system]) system = proxy.system etherdev = system.tsunami.etherdev0 bytes = etherdev.rxBytes + etherdev.txBytes kbytes = bytes / 1024 packets = etherdev.rxPackets + etherdev.txPackets def display(): if options.graph: output.graph(command, options.graphdir, proxy) else: output.display(command, options.printmode) if command == 'ticks': output.stat = system.run0.numCycles display() return if command == 'bytes': output.stat = bytes display() return if command == 'packets': output.stat = packets display() return if command == 'ppt' or command == 'tpp': output.stat = packets / system.run0.numCycles output.invert = command == 'tpp' display() return if command == 'pps': output.stat = packets / source['sim_seconds'] output.ylabel = 'Packets/s' display() return if command == 'bpt' or command == 'tpb': output.stat = bytes / system.run0.numCycles * 8 output.ylabel = 'bps / Hz' output.invert = command == 'tpb' display() return if command in ('rxbps', 'txbps', 'bps'): if command == 'rxbps': output.stat = etherdev.rxBandwidth / 1e9 if command == 'txbps': output.stat = etherdev.txBandwidth / 1e9 if command == 'bps': output.stat = (etherdev.rxBandwidth + etherdev.txBandwidth) / 1e9 output.ylabel = 'Bandwidth (Gbps)' output.ylim = [ 0.0, 10.0 ] display() return if command == 'bpp': output.stat = bytes / packets output.ylabel = 'Bytes / Packet' display() return if command == 'rxbpp': output.stat = etherdev.rxBytes / etherdev.rxPackets output.ylabel = 'Receive Bytes / Packet' display() return if command == 'txbpp': output.stat = etherdev.txBytes / etherdev.txPackets output.ylabel = 'Transmit Bytes / Packet' display() return if command == 'rtp': output.stat = etherdev.rxPackets / etherdev.txPackets output.ylabel = 'rxPackets / txPackets' display() return if command == 'rtb': output.stat = etherdev.rxBytes / etherdev.txBytes output.ylabel = 'rxBytes / txBytes' display() return misses = system.l2.overall_mshr_misses if command == 'misses': output.stat = misses output.ylabel = 'Overall MSHR Misses' display() return if command == 'mpkb': output.stat = misses / (bytes / 1024) output.ylabel = 'Misses / KB' display() return if command == 'ipkb': interrupts = system.run0.kern.faults[4] output.stat = interrupts / kbytes output.ylabel = 'Interrupts / KB' display() return if command == 'execute': output.stat = system.run0.ISSUE__count display() return if command == 'commit': output.stat = system.run0.COM__count display() return if command == 'fetch': output.stat = system.run0.FETCH__count display() return raise CommandException class Options: pass if __name__ == '__main__': import getpass options = Options() options.host = None options.db = None options.passwd = '' options.user = getpass.getuser() options.runs = None options.system = 'client' options.method = None options.graph = False options.ticks = False options.printmode = 'G' jobfilename = None options.jobfile = None options.all = False opts, args = getopts(sys.argv[1:], '-EFJad:g:h:j:m:pr:s:u:T:') for o,a in opts: if o == '-E': options.printmode = 'E' if o == '-F': options.printmode = 'F' if o == '-a': options.all = True if o == '-d': options.db = a if o == '-g': options.graph = True; options.graphdir = a if o == '-h': options.host = a if o == '-J': jobfilename = None if o == '-j': jobfilename = a if o == '-m': options.method = a if o == '-p': options.passwd = getpass.getpass() if o == '-r': options.runs = a if o == '-u': options.user = a if o == '-s': options.system = a if o == '-T': options.ticks = a if jobfilename: from jobfile import JobFile options.jobfile = JobFile(jobfilename) if not options.host: options.host = options.jobfile.dbhost if not options.db: options.db = options.jobfile.statdb if not options.host: sys.exit('Database server must be provided from a jobfile or -h') if not options.db: sys.exit('Database name must be provided from a jobfile or -d') if len(args) == 0: usage() command = args[0] args = args[1:] try: commands(options, command, args) except CommandException: usage()