#!/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. from __future__ import division import re, sys, math def usage(): print '''\ Usage: %s [-E] [-F] [-d ] [-g ] [-h ] [-p] [-s ] [-r ] [-T ] [-u ] [command args] commands extra parameters description ----------- ------------------ --------------------------------------- bins [regex] List bins (only matching regex) 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 def printval(name, value, invert = False): if invert and value != 0.0: value = 1 / value if value == (1e300*1e300): return if printval.mode == 'G': print '%s: %g' % (name, value) elif printval.mode != 'F' and value > 1e6: print '%s: %0.5e' % (name, value) else: print '%s: %f' % (name, value) printval.mode = 'G' def unique(list): set = {} map(set.__setitem__, list, []) return set.keys() #benchmarks = [ 'm', 's', 'snt', 'nb1', 'w1', 'w2', 'w3', 'w4', 'nm', 'ns', 'nw1', 'nw2', 'nw3' ] def graphdata(runs, options, tag, label, value): import info bench_system = { 'm' : 'client', 's' : 'client', 'snt' : 'client', 'nb1' : 'server', 'nb2' : 'server', 'nt1' : 'server', 'nt2' : 'server', 'w1' : 'server', 'w2' : 'server', 'w3' : 'server', 'w4' : 'server', 'w1s' : 'server', 'w2s' : 'server', 'w3s' : 'server', 'ns' : 'natbox', 'nm' : 'natbox', 'nw1' : 'natbox', 'nw2' : 'natbox', 'nw3' : 'natbox' } system_configs = { 's1' : 'Uni 4GHz', 'm1' : 'Uni 6GHz', 'f1' : 'Uni 8GHz', 'q1' : 'Uni 10GHz', 's2' : 'Dual 4GHz', 'm2' : 'Dual 6GHz', 's4' : 'Quad 4GHz', 'm4' : 'Quad 6GHz' } configs = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ] benchmarks = [ 'm', 'snt', 'w2', 'nm', 'nw2' ] caches = [ '0', '2', '4' ] names = [] for bench in benchmarks: if bench_system[bench] != options.system: continue for cache in caches: names.append([bench, cache]) for bench,cache in names: base = '%s.%s' % (bench, cache) fname = 'data/uni.%s.%s.dat' % (tag, base) f = open(fname, 'w') print >>f, '#set TITLE = ' print >>f, '#set ylbl = %s' % label #print >>f, '#set sublabels = %s' % ' '.join(configs) print >>f, '#set sublabels = ste hte htd ocm occ ocs' for speed in ('s1', 'm1', 'f1', 'q1'): label = system_configs[speed] print >>f, '"%s"' % label, for conf in configs: name = '%s.%s.%s.%s' % (conf, bench, cache, speed) run = info.source.allRunNames[name] info.display_run = run.run; val = float(value) if val == 1e300*1e300: print >>f, 0.0, else: print >>f, "%f" % val, print >>f f.close() configs = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ] benchmarks = [ 'w2'] caches = [ '0', '2', '4' ] names = [] for bench in benchmarks: if bench_system[bench] != options.system: continue for cache in caches: names.append([bench, cache]) for bench,cache in names: base = '%s.%s' % (bench, cache) fname = 'data/mp.%s.%s.dat' % (tag, base) f = open(fname, 'w') print >>f, '#set TITLE = ' print >>f, '#set ylbl = %s' % label #print >>f, '#set sublabels = %s' % ' '.join(configs) print >>f, '#set sublabels = ste hte htd ocm occ ocs' for speed in ('s2', 'm2', 's4', 'm4'): label = system_configs[speed] print >>f, '"%s"' % label, for conf in configs: name = '%s.%s.%s.%s' % (conf, bench, cache, speed) run = info.source.allRunNames[name] info.display_run = run.run; val = float(value) if val == 1e300*1e300: print >>f, 0.0, else: print >>f, "%f" % val, print >>f f.close() def printdata(runs, value, invert = False): import info for run in runs: info.display_run = run.run; val = float(value) printval(run.name, val) 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, info info.source = db.Database() info.source.host = options.host info.source.db = options.db info.source.passwd = options.passwd info.source.user = options.user info.source.connect() info.source.update_dict(globals()) if type(options.get) is str: info.source.get = options.get if options.runs is None: runs = info.source.allRuns else: rx = re.compile(options.runs) runs = [] for run in info.source.allRuns: if rx.match(run.name): runs.append(run) info.display_run = runs[0].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 info.source.listRuns(user) return if command == 'stability': if len(args) < 2: raise CommandException try: merge = int(args[0]) except ValueError: usage() stats = info.source.getStat(args[1]) info.source.get = "sum" #loop through all the stats selected for stat in stats: print "%s:" % stat.name print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \ ("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", "SAMP", "CV") print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \ ("--------------------", "------------", "------------", "----", "-----", "-----", "-----", "----------") #loop through all the selected runs for run in runs: info.display_run = run.run; runTicks = info.source.retTicks([ run ]) #throw away the first one, it's 0 runTicks.pop(0) info.globalTicks = runTicks avg = 0 stdev = 0 numoutsideavg = 0 numoutside1std = 0 numoutside2std = 0 pairRunTicks = [] if float(stat) == 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: info.globalTicks = tick avg += float(stat) avg /= len(pairRunTicks) for tick in pairRunTicks: info.globalTicks = tick val = float(stat) stdev += pow((val-avg),2) stdev = math.sqrt(stdev / len(pairRunTicks)) for tick in pairRunTicks: info.globalTicks = tick val = float(stat) 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: print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \ (run.name, "%.1f" % avg, "%.1f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.3f" % (stdev/avg*100)) elif avg > 100: print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \ (run.name, "%.1f" % avg, "%.1f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.5f" % (stdev/avg*100)) else: print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \ (run.name, "%.5f" % avg, "%.5f" % stdev, "%d" % numoutsideavg, "%d" % numoutside1std, "%d" % numoutside2std, "%d" % len(pairRunTicks), "%.7f" % (stdev/avg*100)) return if command == 'stats': if len(args) == 0: info.source.listStats() elif len(args) == 1: info.source.listStats(args[0]) else: raise CommandException return if command == 'stat': if len(args) != 1: raise CommandException stats = info.source.getStat(args[0]) for stat in stats: if options.graph: graphdata(runs, options, stat.name, stat.name, stat) else: if options.ticks: print 'only displaying sample %s' % options.ticks info.globalTicks = [ int(x) for x in options.ticks.split() ] if options.binned: print 'kernel ticks' stat.bins = 'kernel' printdata(runs, stat) print 'idle ticks' stat.bins = 'idle' printdata(runs, stat) print 'user ticks' stat.bins = 'user' printdata(runs, stat) print 'interrupt ticks' stat.bins = 'interrupt' printdata(runs, stat) print 'total ticks' stat.bins = None print stat.name printdata(runs, stat) return if command == 'formula': if len(args) != 1: raise CommandException stats = eval(args[0]) for stat in stats: if options.graph: graphdata(runs, options, stat.name, stat.name, stat) else: if options.binned: print 'kernel ticks' stat.bins = 'kernel' printdata(runs, stat) print 'idle ticks' stat.bins = 'idle' printdata(runs, stat) print 'user ticks' stat.bins = 'user' printdata(runs, stat) print 'interrupt ticks' stat.bins = 'interrupt' printdata(runs, stat) print 'total ticks' stat.bins = None print args[0] printdata(runs, stat) return if command == 'bins': if len(args) == 0: info.source.listBins() elif len(args) == 1: info.source.listBins(args[0]) else: raise CommandException return if command == 'formulas': if len(args) == 0: info.source.listFormulas() elif len(args) == 1: info.source.listFormulas(args[0]) else: raise CommandException return if command == 'samples': if len(args): raise CommandException info.source.listTicks(runs) return if len(args): raise CommandException system = info.source.__dict__[options.system] if command == 'usertime': import copy kernel = copy.copy(system.full0.numCycles) kernel.bins = 'kernel' user = copy.copy(system.full0.numCycles) user.bins = 'user' if options.graph: graphdata(runs, options, 'usertime', 'User Fraction', user / system.full0.numCycles) else: printdata(runs, user / system.full0.numCycles) return if command == 'ticks': if options.binned: print 'kernel ticks' system.full0.numCycles.bins = 'kernel' printdata(runs, system.full0.numCycles) print 'idle ticks' system.full0.numCycles.bins = 'idle' printdata(runs, system.full0.numCycles) print 'user ticks' system.full0.numCycles.bins = 'user' printdata(runs, system.full0.numCycles) print 'total ticks' system.full0.numCycles.bins = None printdata(runs, system.full0.numCycles) return if command == 'packets': packets = system.tsunami.etherdev0.rxPackets if options.graph: graphdata(runs, options, 'packets', 'Packets', packets) else: printdata(runs, packets) return if command == 'ppt' or command == 'tpp': ppt = system.tsunami.etherdev0.rxPackets / sim_ticks printdata(runs, ppt, command == 'tpp') return if command == 'pps': pps = system.tsunami.etherdev0.rxPackets / sim_seconds if options.graph: graphdata(runs, options, 'pps', 'Packets/s', pps) else: printdata(runs, pps) return if command == 'bpt' or command == 'tpb': bytes = system.tsunami.etherdev0.rxBytes + system.tsunami.etherdev0.txBytes bpt = bytes / sim_ticks * 8 if options.graph: graphdata(runs, options, 'bpt', 'bps / Hz', bpt) else: printdata(runs, bpt, command == 'tpb') return if command == 'bptb' or command == 'tpbb': bytes = system.tsunami.etherdev0.rxBytes + system.tsunami.etherdev0.txBytes print 'kernel stats' bytes.bins = 'kernel' printdata(runs, bytes / ticks) print 'idle stats' bytes.bins = 'idle' printdata(runs, bytes / ticks) print 'user stats' bytes.bins = 'user' printdata(runs, bytes / ticks) return if command == 'bytes': stat = system.tsunami.etherdev0.rxBytes + system.tsunami.etherdev0.txBytes if options.binned: print '%s kernel stats' % stat.name stat.bins = 'kernel' printdata(runs, stat) print '%s idle stats' % stat.name stat.bins = 'idle' printdata(runs, stat) print '%s user stats' % stat.name stat.bins = 'user' printdata(runs, stat) print '%s total stats' % stat.name stat.bins = None printdata(runs, stat) return if command == 'rxbps': gbps = system.tsunami.etherdev0.rxBandwidth / 1e9 if options.graph: graphdata(runs, options, 'rxbps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return if command == 'txbps': gbps = system.tsunami.etherdev0.txBandwidth / 1e9 if options.graph: graphdata(runs, options, 'txbps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return if command == 'bps': rxbps = system.tsunami.etherdev0.rxBandwidth txbps = system.tsunami.etherdev0.txBandwidth gbps = (rxbps + txbps) / 1e9 if options.graph: graphdata(runs, options, 'bps', 'Bandwidth (Gbps)', gbps) else: printdata(runs, gbps) return if command == 'misses': stat = system.l2.overall_mshr_misses if options.binned: print '%s kernel stats' % stat.name stat.bins = 'kernel' printdata(runs, stat) print '%s idle stats' % stat.name stat.bins = 'idle' printdata(runs, stat) print '%s user stats' % stat.name stat.bins = 'user' printdata(runs, stat) print '%s total stats' % stat.name stat.bins = None if options.graph: graphdata(runs, options, 'misses', 'Overall MSHR Misses', stat) else: printdata(runs, stat) return if command == 'mpkb': misses = system.l2.overall_mshr_misses rxbytes = system.tsunami.etherdev0.rxBytes txbytes = system.tsunami.etherdev0.txBytes if options.binned: print 'mpkb kernel stats' misses.bins = 'kernel' mpkb = misses / ((rxbytes + txbytes) / 1024) printdata(runs, mpkb) print 'mpkb idle stats' misses.bins = 'idle' mpkb = misses / ((rxbytes + txbytes) / 1024) printdata(runs, mpkb) print 'mpkb user stats' misses.bins = 'user' mpkb = misses / ((rxbytes + txbytes) / 1024) printdata(runs, mpkb) print 'mpkb total stats' mpkb = misses / ((rxbytes + txbytes) / 1024) misses.bins = None if options.graph: graphdata(runs, options, 'mpkb', 'Misses / KB', mpkb) else: printdata(runs, mpkb) return if command == 'ipkb': interrupts = system.full0.kern.faults[4] rxbytes = system.tsunami.etherdev0.rxBytes txbytes = system.tsunami.etherdev0.txBytes if options.binned: print 'ipkb kernel stats' interrupts.bins = 'kernel' ipkb = interrupts / ((rxbytes + txbytes) / 1024) printdata(runs, ipkb) print 'ipkb idle stats' interrupts.bins = 'idle' ipkb = interrupts / ((rxbytes + txbytes) / 1024) printdata(runs, ipkb) print 'ipkb user stats' interrupts.bins = 'user' ipkb = interrupts / ((rxbytes + txbytes) / 1024) printdata(runs, ipkb) print 'ipkb total stats' ipkb = interrupts / ((rxbytes + txbytes) / 1024) interrupts.bins = None if options.graph: graphdata(runs, options, 'ipkb', 'Interrupts / KB', ipkb) else: printdata(runs, ipkb) return if command == 'execute': printdata(runs, system.full0.ISSUE__count) return if command == 'commit': printdata(runs, system.full0.COM__count) return if command == 'fetch': printdata(runs, system.full0.FETCH__count) return if command == 'bpp': ed = system.tsunami.etherdev0 bpp = (ed.rxBytes + ed.txBytes) / (ed.rxPackets + ed.txPackets) if options.graph: graphdata(runs, options, 'bpp', 'Bytes / Packet', bpp) else: printdata(runs, bpp) return if command == 'rxbpp': bpp = system.tsunami.etherdev0.rxBytes / system.tsunami.etherdev0.rxPackets if options.graph: graphdata(runs, options, 'rxbpp', 'Receive Bytes / Packet', bpp) else: printdata(runs, bpp) return if command == 'txbpp': bpp = system.tsunami.etherdev0.txBytes / system.tsunami.etherdev0.txPackets if options.graph: graphdata(runs, options, 'txbpp', 'Transmit Bytes / Packet', bpp) else: printdata(runs, bpp) return if command == 'rtp': rtp = system.tsunami.etherdev0.rxPackets / system.tsunami.etherdev0.txPackets if options.graph: graphdata(runs, options, 'rtp', 'rxPackets / txPackets', rtp) else: printdata(runs, rtp) return if command == 'rtb': rtb = system.tsunami.etherdev0.rxBytes / system.tsunami.etherdev0.txBytes if options.graph: graphdata(runs, options, 'rtb', 'rxBytes / txBytes', rtb) else: printdata(runs, rtb) return raise CommandException class Options: pass if __name__ == '__main__': import getpass options = Options() options.host = 'zizzer.pool' options.db = None options.passwd = '' options.user = getpass.getuser() options.runs = None options.system = 'client' options.get = None options.binned = False options.graph = False options.ticks = False opts, args = getopts(sys.argv[1:], '-6BEFGd:g:h:pr:s:u:T:') for o,a in opts: if o == '-B': options.binned = True if o == '-E': printval.mode = 'E' if o == '-F': printval.mode = 'F' if o == '-G': options.graph = True; if o == '-d': options.db = a if o == '-g': options.get = a if o == '-h': options.host = 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 len(args) == 0: usage() command = args[0] args = args[1:] try: commands(options, command, args) except CommandException: usage()