stats.py revision 1957
1451SN/A#!/usr/bin/env python 25795Ssaidi@eecs.umich.edu 3451SN/A# Copyright (c) 2003-2004 The Regents of The University of Michigan 4451SN/A# All rights reserved. 5451SN/A# 6451SN/A# Redistribution and use in source and binary forms, with or without 7451SN/A# modification, are permitted provided that the following conditions are 8451SN/A# met: redistributions of source code must retain the above copyright 9451SN/A# notice, this list of conditions and the following disclaimer; 10451SN/A# redistributions in binary form must reproduce the above copyright 11451SN/A# notice, this list of conditions and the following disclaimer in the 12451SN/A# documentation and/or other materials provided with the distribution; 13451SN/A# neither the name of the copyright holders nor the names of its 14451SN/A# contributors may be used to endorse or promote products derived from 15451SN/A# this software without specific prior written permission. 16451SN/A# 17451SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18451SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19451SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20451SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21451SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22451SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23451SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24451SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25451SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26451SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272665Ssaidi@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu 29451SN/Afrom __future__ import division 30451SN/Aimport re, sys, math 31451SN/A 32451SN/Adef usage(): 336215Snate@binkert.org print '''\ 346215Snate@binkert.orgUsage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p] 352093SN/A [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>] 365795Ssaidi@eecs.umich.edu <command> [command args] 372093SN/A 383113Sgblack@eecs.umich.edu commands extra parameters description 392423SN/A ----------- ------------------ --------------------------------------- 405795Ssaidi@eecs.umich.edu bins [regex] List bins (only matching regex) 415795Ssaidi@eecs.umich.edu formula <formula> Evaluated formula specified 425795Ssaidi@eecs.umich.edu formulas [regex] List formulas (only matching regex) 432093SN/A runs none List all runs in database 442093SN/A samples none List samples present in database 452093SN/A stability <pairnum> <stats> Calculated statistical info about stats 462093SN/A stat <regex> Show stat data (only matching regex) 472093SN/A stats [regex] List all stats (only matching regex) 483113Sgblack@eecs.umich.edu 493113Sgblack@eecs.umich.edu database <command> Where command is drop, init, or clean 502093SN/A 512093SN/A''' % sys.argv[0] 522093SN/A sys.exit(1) 532093SN/A 542093SN/Adef getopts(list, flags): 553122Sgblack@eecs.umich.edu import getopt 562093SN/A try: 572093SN/A opts, args = getopt.getopt(list, flags) 586684Stjones1@inf.ed.ac.uk except getopt.GetoptError: 592093SN/A usage() 603122Sgblack@eecs.umich.edu 612093SN/A return opts, args 622093SN/A 632093SN/Aclass CommandException(Exception): 643113Sgblack@eecs.umich.edu pass 653113Sgblack@eecs.umich.edu 663113Sgblack@eecs.umich.edudef commands(options, command, args): 675543Ssaidi@eecs.umich.edu if command == 'database': 685543Ssaidi@eecs.umich.edu if len(args) == 0: raise CommandException 695543Ssaidi@eecs.umich.edu 705543Ssaidi@eecs.umich.edu import dbinit 715543Ssaidi@eecs.umich.edu mydb = dbinit.MyDB(options) 725543Ssaidi@eecs.umich.edu 735543Ssaidi@eecs.umich.edu if args[0] == 'drop': 745543Ssaidi@eecs.umich.edu if len(args) > 2: raise CommandException 755543Ssaidi@eecs.umich.edu mydb.admin() 765543Ssaidi@eecs.umich.edu mydb.drop() 775543Ssaidi@eecs.umich.edu if len(args) == 2 and args[1] == 'init': 785543Ssaidi@eecs.umich.edu mydb.create() 795543Ssaidi@eecs.umich.edu mydb.connect() 805543Ssaidi@eecs.umich.edu mydb.populate() 815543Ssaidi@eecs.umich.edu mydb.close() 825543Ssaidi@eecs.umich.edu return 833113Sgblack@eecs.umich.edu 842093SN/A if args[0] == 'init': 852093SN/A if len(args) > 1: raise CommandException 863113Sgblack@eecs.umich.edu mydb.admin() 875543Ssaidi@eecs.umich.edu mydb.create() 885543Ssaidi@eecs.umich.edu mydb.connect() 895543Ssaidi@eecs.umich.edu mydb.populate() 905543Ssaidi@eecs.umich.edu mydb.close() 915543Ssaidi@eecs.umich.edu return 922093SN/A 935543Ssaidi@eecs.umich.edu if args[0] == 'clean': 945543Ssaidi@eecs.umich.edu if len(args) > 1: raise CommandException 955543Ssaidi@eecs.umich.edu mydb.connect() 965543Ssaidi@eecs.umich.edu mydb.clean() 975543Ssaidi@eecs.umich.edu return 985543Ssaidi@eecs.umich.edu 992093SN/A raise CommandException 1005543Ssaidi@eecs.umich.edu 1015543Ssaidi@eecs.umich.edu import db, info 1025543Ssaidi@eecs.umich.edu info.source = db.Database() 1035543Ssaidi@eecs.umich.edu info.source.host = options.host 1045543Ssaidi@eecs.umich.edu info.source.db = options.db 1055543Ssaidi@eecs.umich.edu info.source.passwd = options.passwd 1065543Ssaidi@eecs.umich.edu info.source.user = options.user 1073113Sgblack@eecs.umich.edu info.source.connect() 1082093SN/A #info.source.update_dict(globals()) 1092093SN/A 1102093SN/A if type(options.get) is str: 1112093SN/A info.source.get = options.get 1122093SN/A 1132093SN/A if options.runs is None: 1145543Ssaidi@eecs.umich.edu runs = info.source.allRuns 1155543Ssaidi@eecs.umich.edu else: 1165543Ssaidi@eecs.umich.edu rx = re.compile(options.runs) 1175543Ssaidi@eecs.umich.edu runs = [] 1185543Ssaidi@eecs.umich.edu for run in info.source.allRuns: 1192093SN/A if rx.match(run.name): 1202093SN/A runs.append(run) 1212093SN/A 1222093SN/A info.display_run = runs[0].run 1235543Ssaidi@eecs.umich.edu 1245543Ssaidi@eecs.umich.edu if command == 'runs': 1252093SN/A user = None 1262093SN/A opts, args = getopts(args, '-u') 1272093SN/A if len(args): 1282093SN/A raise CommandException 1295543Ssaidi@eecs.umich.edu for o,a in opts: 1305543Ssaidi@eecs.umich.edu if o == '-u': 1312093SN/A user = a 1322093SN/A info.source.listRuns(user) 1336683Stjones1@inf.ed.ac.uk return 1346744SAli.Saidi@arm.com 1356683Stjones1@inf.ed.ac.uk if command == 'stats': 1366683Stjones1@inf.ed.ac.uk if len(args) == 0: 1376683Stjones1@inf.ed.ac.uk info.source.listStats() 1386683Stjones1@inf.ed.ac.uk elif len(args) == 1: 1396683Stjones1@inf.ed.ac.uk info.source.listStats(args[0]) 1406683Stjones1@inf.ed.ac.uk else: 1416683Stjones1@inf.ed.ac.uk raise CommandException 1426683Stjones1@inf.ed.ac.uk 1436683Stjones1@inf.ed.ac.uk return 1442093SN/A 1452093SN/A if command == 'bins': 1462093SN/A if len(args) == 0: 1472093SN/A info.source.listBins() 1482093SN/A elif len(args) == 1: 1492093SN/A info.source.listBins(args[0]) 1502093SN/A else: 1512093SN/A raise CommandException 1522093SN/A 1535543Ssaidi@eecs.umich.edu return 1545543Ssaidi@eecs.umich.edu 1555543Ssaidi@eecs.umich.edu if command == 'formulas': 1565543Ssaidi@eecs.umich.edu if len(args) == 0: 1575543Ssaidi@eecs.umich.edu info.source.listFormulas() 1585543Ssaidi@eecs.umich.edu elif len(args) == 1: 1595543Ssaidi@eecs.umich.edu info.source.listFormulas(args[0]) 1605543Ssaidi@eecs.umich.edu else: 1615543Ssaidi@eecs.umich.edu raise CommandException 1625543Ssaidi@eecs.umich.edu 1635543Ssaidi@eecs.umich.edu return 1645543Ssaidi@eecs.umich.edu 1655543Ssaidi@eecs.umich.edu if command == 'samples': 1665543Ssaidi@eecs.umich.edu if len(args): 1675543Ssaidi@eecs.umich.edu raise CommandException 1685543Ssaidi@eecs.umich.edu 1692093SN/A info.source.listTicks(runs) 1702093SN/A return 1715795Ssaidi@eecs.umich.edu 1725795Ssaidi@eecs.umich.edu if command == 'stability': 1735795Ssaidi@eecs.umich.edu if len(args) < 2: 1749112Smarc.orr@gmail.com raise CommandException 1759112Smarc.orr@gmail.com 1769112Smarc.orr@gmail.com try: 1779112Smarc.orr@gmail.com merge = int(args[0]) 1789112Smarc.orr@gmail.com except ValueError: 1799112Smarc.orr@gmail.com usage() 1802093SN/A stats = info.source.getStat(args[1]) 1812093SN/A info.source.get = "sum" 182451SN/A 183 def disp(*args): 184 print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args 185 186 # temporary variable containing a bunch of dashes 187 d = '-' * 100 188 189 #loop through all the stats selected 190 for stat in stats: 191 print "%s:" % stat.name 192 disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", 193 "SAMP", "CV") 194 disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10]) 195 196 #loop through all the selected runs 197 for run in runs: 198 info.display_run = run.run; 199 runTicks = info.source.retTicks([ run ]) 200 #throw away the first one, it's 0 201 runTicks.pop(0) 202 info.globalTicks = runTicks 203 avg = 0 204 stdev = 0 205 numoutsideavg = 0 206 numoutside1std = 0 207 numoutside2std = 0 208 pairRunTicks = [] 209 if float(stat) == 1e300*1e300: 210 continue 211 for t in range(0, len(runTicks)-(merge-1), merge): 212 tempPair = [] 213 for p in range(0,merge): 214 tempPair.append(runTicks[t+p]) 215 pairRunTicks.append(tempPair) 216 #loop through all the various ticks for each run 217 for tick in pairRunTicks: 218 info.globalTicks = tick 219 avg += float(stat) 220 avg /= len(pairRunTicks) 221 for tick in pairRunTicks: 222 info.globalTicks = tick 223 val = float(stat) 224 stdev += pow((val-avg),2) 225 stdev = math.sqrt(stdev / len(pairRunTicks)) 226 for tick in pairRunTicks: 227 info.globalTicks = tick 228 val = float(stat) 229 if (val < (avg * .9)) or (val > (avg * 1.1)): 230 numoutsideavg += 1 231 if (val < (avg - stdev)) or (val > (avg + stdev)): 232 numoutside1std += 1 233 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))): 234 numoutside2std += 1 235 if avg > 1000: 236 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 237 "%d" % numoutsideavg, "%d" % numoutside1std, 238 "%d" % numoutside2std, "%d" % len(pairRunTicks), 239 "%.3f" % (stdev/avg*100)) 240 elif avg > 100: 241 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 242 "%d" % numoutsideavg, "%d" % numoutside1std, 243 "%d" % numoutside2std, "%d" % len(pairRunTicks), 244 "%.5f" % (stdev/avg*100)) 245 else: 246 disp(run.name, "%.5f" % avg, "%.5f" % stdev, 247 "%d" % numoutsideavg, "%d" % numoutside1std, 248 "%d" % numoutside2std, "%d" % len(pairRunTicks), 249 "%.7f" % (stdev/avg*100)) 250 return 251 252 if command == 'all': 253 if len(args): 254 raise CommandException 255 256 all = [ 'bps', 'rxbps', 'txbps', 'bpt', 257 'misses', 'mpkb', 258 'ipkb', 259 'pps', 'bpp', 'txbpp', 'rxbpp', 260 'rtp', 'rtb' ] 261 for command in all: 262 commands(options, command, args) 263 264 if options.ticks: 265 if not options.graph: 266 print 'only displaying sample %s' % options.ticks 267 info.globalTicks = [ int(x) for x in options.ticks.split() ] 268 269 from output import StatOutput 270 271 def display(): 272 if options.graph: 273 output.graph(options.graphdir) 274 else: 275 output.display(options.binned, options.printmode) 276 277 278 if command == 'stat' or command == 'formula': 279 if len(args) != 1: 280 raise CommandException 281 282 if command == 'stat': 283 stats = info.source.getStat(args[0]) 284 if command == 'formula': 285 stats = eval(args[0]) 286 287 for stat in stats: 288 output = StatOutput(stat.name, options.jobfile) 289 output.stat = stat 290 output.label = stat.name 291 display() 292 293 return 294 295 if len(args): 296 raise CommandException 297 298 system = info.source.__dict__[options.system] 299 300 from proxy import ProxyGroup 301 sim_ticks = info.source['sim_ticks'] 302 sim_seconds = info.source['sim_seconds'] 303 proxy = ProxyGroup(system = info.source[options.system]) 304 system = proxy.system 305 306 etherdev = system.tsunami.etherdev0 307 bytes = etherdev.rxBytes + etherdev.txBytes 308 kbytes = bytes / 1024 309 packets = etherdev.rxPackets + etherdev.txPackets 310 bps = etherdev.rxBandwidth + etherdev.txBandwidth 311 312 output = StatOutput(command, options.jobfile) 313 314 if command == 'usertime': 315 import copy 316 user = copy.copy(system.full0.numCycles) 317 user.bins = 'user' 318 319 output.stat = user / system.full0.numCycles 320 output.label = 'User Fraction' 321 322 display() 323 return 324 325 if command == 'ticks': 326 output.stat = system.full0.numCycles 327 output.binstats = [ system.full0.numCycles ] 328 329 display() 330 return 331 332 if command == 'bytes': 333 output.stat = bytes 334 display() 335 return 336 337 if command == 'packets': 338 output.stat = packets 339 display() 340 return 341 342 if command == 'ppt' or command == 'tpp': 343 output.stat = packets / sim_ticks 344 output.invert = command == 'tpp' 345 display() 346 return 347 348 if command == 'pps': 349 output.stat = packets / sim_seconds 350 output.label = 'Packets/s' 351 display() 352 return 353 354 if command == 'bpt' or command == 'tpb': 355 output.stat = bytes / sim_ticks * 8 356 output.label = 'bps / Hz' 357 output.invert = command == 'tpb' 358 display() 359 return 360 361 if command == 'rxbps': 362 output.stat = etherdev.rxBandwidth / 1e9 363 output.label = 'Bandwidth (Gbps)' 364 display() 365 return 366 367 if command == 'txbps': 368 output.stat = etherdev.txBandwidth / 1e9 369 output.label = 'Bandwidth (Gbps)' 370 display() 371 return 372 373 if command == 'bps': 374 output.stat = bps / 1e9 375 output.label = 'Bandwidth (Gbps)' 376 display() 377 return 378 379 if command == 'bpp': 380 output.stat = bytes / packets 381 output.label = 'Bytes / Packet' 382 display() 383 return 384 385 if command == 'rxbpp': 386 output.stat = etherdev.rxBytes / etherdev.rxPackets 387 output.label = 'Receive Bytes / Packet' 388 display() 389 return 390 391 if command == 'txbpp': 392 output.stat = etherdev.txBytes / etherdev.txPackets 393 output.label = 'Transmit Bytes / Packet' 394 display() 395 return 396 397 if command == 'rtp': 398 output.stat = etherdev.rxPackets / etherdev.txPackets 399 output.label = 'rxPackets / txPackets' 400 display() 401 return 402 403 if command == 'rtb': 404 output.stat = etherdev.rxBytes / etherdev.txBytes 405 output.label = 'rxBytes / txBytes' 406 display() 407 return 408 409 misses = system.l2.overall_mshr_misses 410 411 if command == 'misses': 412 output.stat = misses 413 output.label = 'Overall MSHR Misses' 414 display() 415 return 416 417 if command == 'mpkb': 418 output.stat = misses / (bytes / 1024) 419 output.binstats = [ misses ] 420 output.label = 'Misses / KB' 421 display() 422 return 423 424 if command == 'ipkb': 425 interrupts = system.full0.kern.faults[4] 426 output.stat = interrupts / kbytes 427 output.binstats = [ interrupts ] 428 output.label = 'Interrupts / KB' 429 display() 430 return 431 432 if command == 'execute': 433 output.stat = system.full0.ISSUE__count 434 display() 435 return 436 437 if command == 'commit': 438 output.stat = system.full0.COM__count 439 display() 440 return 441 442 if command == 'fetch': 443 output.stat = system.full0.FETCH__count 444 display() 445 return 446 447 raise CommandException 448 449 450class Options: pass 451 452if __name__ == '__main__': 453 import getpass 454 from jobfile import JobFile 455 456 options = Options() 457 options.host = None 458 options.db = None 459 options.passwd = '' 460 options.user = getpass.getuser() 461 options.runs = None 462 options.system = 'client' 463 options.get = None 464 options.binned = False 465 options.graph = False 466 options.ticks = False 467 options.printmode = 'G' 468 jobfilename = 'Test.py' 469 options.jobfile = None 470 options.all = False 471 472 opts, args = getopts(sys.argv[1:], '-BEFG:Jad:g:h:j:pr:s:u:T:') 473 for o,a in opts: 474 if o == '-B': 475 options.binned = True 476 if o == '-E': 477 options.printmode = 'E' 478 if o == '-F': 479 options.printmode = 'F' 480 if o == '-G': 481 options.get = a 482 if o == '-a': 483 options.all = True 484 if o == '-d': 485 options.db = a 486 if o == '-g': 487 options.graph = True; 488 options.graphdir = a 489 if o == '-h': 490 options.host = a 491 if o == '-J': 492 jobfilename = None 493 if o == '-j': 494 jobfilename = a 495 if o == '-p': 496 options.passwd = getpass.getpass() 497 if o == '-r': 498 options.runs = a 499 if o == '-u': 500 options.user = a 501 if o == '-s': 502 options.system = a 503 if o == '-T': 504 options.ticks = a 505 506 if jobfilename: 507 options.jobfile = JobFile(jobfilename) 508 if not options.host: 509 options.host = options.jobfile.dbhost 510 if not options.db: 511 options.db = options.jobfile.statdb 512 513 if not options.host: 514 sys.exit('Database server must be provided from a jobfile or -h') 515 516 if not options.db: 517 sys.exit('Database name must be provided from a jobfile or -d') 518 519 if len(args) == 0: 520 usage() 521 522 command = args[0] 523 args = args[1:] 524 525 try: 526 commands(options, command, args) 527 except CommandException: 528 usage() 529