#!/usr/bin/env python # 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 <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p] [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>] <command> [command args] commands extra parameters description ----------- ------------------ --------------------------------------- formula <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 <pairnum> <stats> Calculated statistical info about stats stat <regex> Show stat data (only matching regex) stats [regex] List all stats (only matching regex) database <command> 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()