486 lines
14 KiB
Python
Executable file
486 lines
14 KiB
Python
Executable file
#!/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()
|