| #!/usr/bin/env python2.7 | |
| # 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() |