stats.py revision 2005
13560SN/A#!/usr/bin/env python 23560SN/A 33560SN/A# Copyright (c) 2003-2004 The Regents of The University of Michigan 43560SN/A# All rights reserved. 53560SN/A# 63560SN/A# Redistribution and use in source and binary forms, with or without 73560SN/A# modification, are permitted provided that the following conditions are 83560SN/A# met: redistributions of source code must retain the above copyright 93560SN/A# notice, this list of conditions and the following disclaimer; 103560SN/A# redistributions in binary form must reproduce the above copyright 113560SN/A# notice, this list of conditions and the following disclaimer in the 123560SN/A# documentation and/or other materials provided with the distribution; 133560SN/A# neither the name of the copyright holders nor the names of its 143560SN/A# contributors may be used to endorse or promote products derived from 153560SN/A# this software without specific prior written permission. 163560SN/A# 173560SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 183560SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 193560SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 203560SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 213560SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 223560SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 233560SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 243560SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 253560SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 263560SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 273560SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 283560SN/A 293560SN/Afrom __future__ import division 303560SN/Aimport re, sys, math 313560SN/A 323560SN/Adef usage(): 333560SN/A print '''\ 343560SN/AUsage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p] 353560SN/A [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>] 365191Ssaidi@eecs.umich.edu <command> [command args] 373565Sgblack@eecs.umich.edu 383560SN/A commands extra parameters description 393560SN/A ----------- ------------------ --------------------------------------- 403560SN/A bins [regex] List bins (only matching regex) 413560SN/A formula <formula> Evaluated formula specified 423560SN/A formulas [regex] List formulas (only matching regex) 433560SN/A runs none List all runs in database 443560SN/A samples none List samples present in database 453560SN/A stability <pairnum> <stats> Calculated statistical info about stats 463560SN/A stat <regex> Show stat data (only matching regex) 473560SN/A stats [regex] List all stats (only matching regex) 483560SN/A 493560SN/A database <command> Where command is drop, init, or clean 503560SN/A 513560SN/A''' % sys.argv[0] 523560SN/A sys.exit(1) 533560SN/A 543560SN/Adef getopts(list, flags): 553560SN/A import getopt 563560SN/A try: 573560SN/A opts, args = getopt.getopt(list, flags) 583560SN/A except getopt.GetoptError: 593560SN/A usage() 603560SN/A 613560SN/A return opts, args 623560SN/A 633560SN/Aclass CommandException(Exception): 643560SN/A pass 653560SN/A 663560SN/Adef commands(options, command, args): 673560SN/A if command == 'database': 683560SN/A if len(args) == 0: raise CommandException 693560SN/A 703560SN/A import dbinit 713560SN/A mydb = dbinit.MyDB(options) 723560SN/A 733560SN/A if args[0] == 'drop': 743560SN/A if len(args) > 2: raise CommandException 753560SN/A mydb.admin() 763560SN/A mydb.drop() 773560SN/A if len(args) == 2 and args[1] == 'init': 783560SN/A mydb.create() 793560SN/A mydb.connect() 803560SN/A mydb.populate() 813560SN/A mydb.close() 823560SN/A return 833560SN/A 843560SN/A if args[0] == 'init': 853560SN/A if len(args) > 1: raise CommandException 863560SN/A mydb.admin() 873560SN/A mydb.create() 883560SN/A mydb.connect() 893560SN/A mydb.populate() 903560SN/A mydb.close() 913560SN/A return 923560SN/A 933560SN/A if args[0] == 'clean': 943560SN/A if len(args) > 1: raise CommandException 953560SN/A mydb.connect() 963560SN/A mydb.clean() 973560SN/A return 983560SN/A 993560SN/A raise CommandException 1003560SN/A 1013560SN/A import db 1023560SN/A source = db.Database() 1033560SN/A source.host = options.host 1043560SN/A source.db = options.db 1053560SN/A source.passwd = options.passwd 1063560SN/A source.user = options.user 1073560SN/A source.connect() 1083560SN/A #source.update_dict(globals()) 1093560SN/A 1103560SN/A if type(options.method) is str: 1113560SN/A source.method = options.method 1123560SN/A 1133560SN/A if options.runs is None: 1143560SN/A runs = source.allRuns 1153560SN/A else: 1163560SN/A rx = re.compile(options.runs) 1173560SN/A runs = [] 1183560SN/A for run in source.allRuns: 1193560SN/A if rx.match(run.name): 1203560SN/A runs.append(run) 1213560SN/A 1223560SN/A if command == 'runs': 1233560SN/A user = None 1243560SN/A opts, args = getopts(args, '-u') 1253560SN/A if len(args): 1263560SN/A raise CommandException 1273560SN/A for o,a in opts: 1283560SN/A if o == '-u': 1293560SN/A user = a 1303560SN/A source.listRuns(user) 1313560SN/A return 1323560SN/A 1333560SN/A if command == 'stats': 1343560SN/A if len(args) == 0: 1353560SN/A source.listStats() 1363560SN/A elif len(args) == 1: 1373560SN/A source.listStats(args[0]) 1383560SN/A else: 1393560SN/A raise CommandException 1403560SN/A 1415191Ssaidi@eecs.umich.edu return 1425191Ssaidi@eecs.umich.edu 1435191Ssaidi@eecs.umich.edu if command == 'bins': 1443560SN/A if len(args) == 0: 1453560SN/A source.listBins() 1467823Ssteve.reinhardt@amd.com elif len(args) == 1: 1473560SN/A source.listBins(args[0]) 1487823Ssteve.reinhardt@amd.com else: 1493560SN/A raise CommandException 1503560SN/A 1513560SN/A return 1523560SN/A 1533560SN/A if command == 'formulas': 1543560SN/A if len(args) == 0: 1555568Snate@binkert.org source.listFormulas() 1563560SN/A elif len(args) == 1: 1573560SN/A source.listFormulas(args[0]) 1583560SN/A else: 1593560SN/A raise CommandException 1603560SN/A 1613560SN/A return 1623560SN/A 1633560SN/A if command == 'samples': 1643560SN/A if len(args): 1653560SN/A raise CommandException 1663560SN/A 1673560SN/A source.listTicks(runs) 1683560SN/A return 1693560SN/A 1705191Ssaidi@eecs.umich.edu if command == 'stability': 1715191Ssaidi@eecs.umich.edu if len(args) < 2: 1725191Ssaidi@eecs.umich.edu raise CommandException 1735191Ssaidi@eecs.umich.edu 1743560SN/A try: 1753560SN/A merge = int(args[0]) 1763560SN/A except ValueError: 1773560SN/A usage() 1783560SN/A stats = source.getStat(args[1]) 1793560SN/A source.method = 'sum' 1803560SN/A 1813560SN/A def disp(*args): 1823560SN/A print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args 1833560SN/A 1843560SN/A # temporary variable containing a bunch of dashes 1853560SN/A d = '-' * 100 1863560SN/A 1873560SN/A #loop through all the stats selected 1883560SN/A for stat in stats: 1893560SN/A print "%s:" % stat.name 1903560SN/A disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", 1913560SN/A "SAMP", "CV") 1923560SN/A disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10]) 1933560SN/A 1943560SN/A #loop through all the selected runs 1953560SN/A for run in runs: 1963560SN/A runTicks = source.retTicks([ run ]) 1973560SN/A #throw away the first one, it's 0 1983560SN/A runTicks.pop(0) 1993560SN/A source.ticks = runTicks 2003560SN/A avg = 0 2013560SN/A stdev = 0 2023560SN/A numoutsideavg = 0 2033560SN/A numoutside1std = 0 2043560SN/A numoutside2std = 0 2053560SN/A pairRunTicks = [] 2063560SN/A if value(stat, run.run) == 1e300*1e300: 2073560SN/A continue 2083560SN/A for t in range(0, len(runTicks)-(merge-1), merge): 2093560SN/A tempPair = [] 2103560SN/A for p in range(0,merge): 2113560SN/A tempPair.append(runTicks[t+p]) 2123560SN/A pairRunTicks.append(tempPair) 2133560SN/A #loop through all the various ticks for each run 2143560SN/A for tick in pairRunTicks: 2153560SN/A source.ticks = tick 2165568Snate@binkert.org avg += value(stat, run.run) 2175568Snate@binkert.org avg /= len(pairRunTicks) 218 for tick in pairRunTicks: 219 source.ticks = tick 220 val = value(stat, run.run) 221 stdev += pow((val-avg),2) 222 stdev = math.sqrt(stdev / len(pairRunTicks)) 223 for tick in pairRunTicks: 224 source.ticks = tick 225 val = value(stat, run.run) 226 if (val < (avg * .9)) or (val > (avg * 1.1)): 227 numoutsideavg += 1 228 if (val < (avg - stdev)) or (val > (avg + stdev)): 229 numoutside1std += 1 230 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))): 231 numoutside2std += 1 232 if avg > 1000: 233 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 234 "%d" % numoutsideavg, "%d" % numoutside1std, 235 "%d" % numoutside2std, "%d" % len(pairRunTicks), 236 "%.3f" % (stdev/avg*100)) 237 elif avg > 100: 238 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 239 "%d" % numoutsideavg, "%d" % numoutside1std, 240 "%d" % numoutside2std, "%d" % len(pairRunTicks), 241 "%.5f" % (stdev/avg*100)) 242 else: 243 disp(run.name, "%.5f" % avg, "%.5f" % stdev, 244 "%d" % numoutsideavg, "%d" % numoutside1std, 245 "%d" % numoutside2std, "%d" % len(pairRunTicks), 246 "%.7f" % (stdev/avg*100)) 247 return 248 249 if command == 'all': 250 if len(args): 251 raise CommandException 252 253 all = [ 'bps', 'misses', 'mpkb', 'ipkb', 'pps', 'bpt' ] 254 for command in all: 255 commands(options, command, args) 256 257 if options.ticks: 258 if not options.graph: 259 print 'only displaying sample %s' % options.ticks 260 source.ticks = [ int(x) for x in options.ticks.split() ] 261 262 import output 263 264 def display(): 265 if options.graph: 266 output.graph(options.graphdir) 267 else: 268 output.display(options.binned, options.printmode) 269 270 271 if command == 'stat' or command == 'formula': 272 if len(args) != 1: 273 raise CommandException 274 275 if command == 'stat': 276 stats = source.getStat(args[0]) 277 if command == 'formula': 278 stats = eval(args[0]) 279 280 for stat in stats: 281 output = output.StatOutput(stat.name, options.jobfile, source) 282 output.stat = stat 283 output.label = stat.name 284 display() 285 286 return 287 288 if len(args): 289 raise CommandException 290 291 system = source.__dict__[options.system] 292 from info import ProxyGroup 293 sim_seconds = source['sim_seconds'] 294 proxy = ProxyGroup(system = source[options.system]) 295 system = proxy.system 296 297 etherdev = system.tsunami.etherdev0 298 bytes = etherdev.rxBytes + etherdev.txBytes 299 kbytes = bytes / 1024 300 packets = etherdev.rxPackets + etherdev.txPackets 301 bps = etherdev.rxBandwidth + etherdev.txBandwidth 302 303 output = output.StatOutput(command, options.jobfile, source) 304 305 if command == 'usertime': 306 import copy 307 user = copy.copy(system.run0.numCycles) 308 user.bins = 'user' 309 310 output.stat = user / system.run0.numCycles 311 output.label = 'User Fraction' 312 313 display() 314 return 315 316 if command == 'ticks': 317 output.stat = system.run0.numCycles 318 output.binstats = [ system.run0.numCycles ] 319 320 display() 321 return 322 323 if command == 'bytes': 324 output.stat = bytes 325 display() 326 return 327 328 if command == 'packets': 329 output.stat = packets 330 display() 331 return 332 333 if command == 'ppt' or command == 'tpp': 334 output.stat = packets / system.run0.numCycles 335 output.invert = command == 'tpp' 336 display() 337 return 338 339 if command == 'pps': 340 output.stat = packets / sim_seconds 341 output.label = 'Packets/s' 342 display() 343 return 344 345 if command == 'bpt' or command == 'tpb': 346 output.stat = bytes / system.run0.numCycles * 8 347 output.label = 'bps / Hz' 348 output.invert = command == 'tpb' 349 display() 350 return 351 352 if command in ('rxbps', 'txbps', 'bps'): 353 if command == 'rxbps': 354 output.stat = etherdev.rxBandwidth / 1e9 355 if command == 'txbps': 356 output.stat = etherdev.txBandwidth / 1e9 357 if command == 'bps': 358 output.stat = bps / 1e9 359 360 output.label = 'Bandwidth (Gbps)' 361 display() 362 return 363 364 if command == 'bpp': 365 output.stat = bytes / packets 366 output.label = 'Bytes / Packet' 367 display() 368 return 369 370 if command == 'rxbpp': 371 output.stat = etherdev.rxBytes / etherdev.rxPackets 372 output.label = 'Receive Bytes / Packet' 373 display() 374 return 375 376 if command == 'txbpp': 377 output.stat = etherdev.txBytes / etherdev.txPackets 378 output.label = 'Transmit Bytes / Packet' 379 display() 380 return 381 382 if command == 'rtp': 383 output.stat = etherdev.rxPackets / etherdev.txPackets 384 output.label = 'rxPackets / txPackets' 385 display() 386 return 387 388 if command == 'rtb': 389 output.stat = etherdev.rxBytes / etherdev.txBytes 390 output.label = 'rxBytes / txBytes' 391 display() 392 return 393 394 misses = system.l2.overall_mshr_misses 395 396 if command == 'misses': 397 output.stat = misses 398 output.label = 'Overall MSHR Misses' 399 display() 400 return 401 402 if command == 'mpkb': 403 output.stat = misses / (bytes / 1024) 404 output.binstats = [ misses ] 405 output.label = 'Misses / KB' 406 display() 407 return 408 409 if command == 'ipkb': 410 interrupts = system.run0.kern.faults[4] 411 output.stat = interrupts / kbytes 412 output.binstats = [ interrupts ] 413 output.label = 'Interrupts / KB' 414 display() 415 return 416 417 if command == 'execute': 418 output.stat = system.run0.ISSUE__count 419 display() 420 return 421 422 if command == 'commit': 423 output.stat = system.run0.COM__count 424 display() 425 return 426 427 if command == 'fetch': 428 output.stat = system.run0.FETCH__count 429 display() 430 return 431 432 raise CommandException 433 434 435class Options: pass 436 437if __name__ == '__main__': 438 import getpass 439 from jobfile import JobFile 440 441 options = Options() 442 options.host = None 443 options.db = None 444 options.passwd = '' 445 options.user = getpass.getuser() 446 options.runs = None 447 options.system = 'client' 448 options.method = None 449 options.binned = False 450 options.graph = False 451 options.ticks = False 452 options.printmode = 'G' 453 jobfilename = 'Test.py' 454 options.jobfile = None 455 options.all = False 456 457 opts, args = getopts(sys.argv[1:], '-BEFJad:g:h:j:m:pr:s:u:T:') 458 for o,a in opts: 459 if o == '-B': 460 options.binned = True 461 if o == '-E': 462 options.printmode = 'E' 463 if o == '-F': 464 options.printmode = 'F' 465 if o == '-a': 466 options.all = True 467 if o == '-d': 468 options.db = a 469 if o == '-g': 470 options.graph = True; 471 options.graphdir = a 472 if o == '-h': 473 options.host = a 474 if o == '-J': 475 jobfilename = None 476 if o == '-j': 477 jobfilename = a 478 if o == '-m': 479 options.method = a 480 if o == '-p': 481 options.passwd = getpass.getpass() 482 if o == '-r': 483 options.runs = a 484 if o == '-u': 485 options.user = a 486 if o == '-s': 487 options.system = a 488 if o == '-T': 489 options.ticks = a 490 491 if jobfilename: 492 options.jobfile = JobFile(jobfilename) 493 if not options.host: 494 options.host = options.jobfile.dbhost 495 if not options.db: 496 options.db = options.jobfile.statdb 497 498 if not options.host: 499 sys.exit('Database server must be provided from a jobfile or -h') 500 501 if not options.db: 502 sys.exit('Database name must be provided from a jobfile or -d') 503 504 if len(args) == 0: 505 usage() 506 507 command = args[0] 508 args = args[1:] 509 510 try: 511 commands(options, command, args) 512 except CommandException: 513 usage() 514