stats.py revision 2343
1#!/usr/bin/env python 2 3# Copyright (c) 2003-2004 The Regents of The University of Michigan 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer; 10# redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution; 13# neither the name of the copyright holders nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29from __future__ import division 30import re, sys, math 31 32def usage(): 33 print '''\ 34Usage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p] 35 [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>] 36 <command> [command args] 37 38 commands extra parameters description 39 ----------- ------------------ --------------------------------------- 40 formula <formula> Evaluated formula specified 41 formulas [regex] List formulas (only matching regex) 42 runs none List all runs in database 43 samples none List samples present in database 44 stability <pairnum> <stats> Calculated statistical info about stats 45 stat <regex> Show stat data (only matching regex) 46 stats [regex] List all stats (only matching regex) 47 48 database <command> Where command is drop, init, or clean 49 50''' % sys.argv[0] 51 sys.exit(1) 52 53def getopts(list, flags): 54 import getopt 55 try: 56 opts, args = getopt.getopt(list, flags) 57 except getopt.GetoptError: 58 usage() 59 60 return opts, args 61 62class CommandException(Exception): 63 pass 64 65def commands(options, command, args): 66 if command == 'database': 67 if len(args) == 0: raise CommandException 68 69 import dbinit 70 mydb = dbinit.MyDB(options) 71 72 if args[0] == 'drop': 73 if len(args) > 2: raise CommandException 74 mydb.admin() 75 mydb.drop() 76 if len(args) == 2 and args[1] == 'init': 77 mydb.create() 78 mydb.connect() 79 mydb.populate() 80 mydb.close() 81 return 82 83 if args[0] == 'init': 84 if len(args) > 1: raise CommandException 85 mydb.admin() 86 mydb.create() 87 mydb.connect() 88 mydb.populate() 89 mydb.close() 90 return 91 92 if args[0] == 'clean': 93 if len(args) > 1: raise CommandException 94 mydb.connect() 95 mydb.clean() 96 return 97 98 raise CommandException 99 100 import db 101 source = db.Database() 102 source.host = options.host 103 source.db = options.db 104 source.passwd = options.passwd 105 source.user = options.user 106 source.connect() 107 #source.update_dict(globals()) 108 109 if type(options.method) is str: 110 source.method = options.method 111 112 if options.runs is None: 113 runs = source.allRuns 114 else: 115 rx = re.compile(options.runs) 116 runs = [] 117 for run in source.allRuns: 118 if rx.match(run.name): 119 runs.append(run) 120 121 if command == 'runs': 122 user = None 123 opts, args = getopts(args, '-u') 124 if len(args): 125 raise CommandException 126 for o,a in opts: 127 if o == '-u': 128 user = a 129 source.listRuns(user) 130 return 131 132 if command == 'stats': 133 if len(args) == 0: 134 source.listStats() 135 elif len(args) == 1: 136 source.listStats(args[0]) 137 else: 138 raise CommandException 139 140 return 141 142 if command == 'formulas': 143 if len(args) == 0: 144 source.listFormulas() 145 elif len(args) == 1: 146 source.listFormulas(args[0]) 147 else: 148 raise CommandException 149 150 return 151 152 if command == 'samples': 153 if len(args): 154 raise CommandException 155 156 source.listTicks(runs) 157 return 158 159 if command == 'stability': 160 if len(args) < 2: 161 raise CommandException 162 163 try: 164 merge = int(args[0]) 165 except ValueError: 166 usage() 167 stats = source.getStat(args[1]) 168 source.method = 'sum' 169 170 def disp(*args): 171 print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args 172 173 # temporary variable containing a bunch of dashes 174 d = '-' * 100 175 176 #loop through all the stats selected 177 for stat in stats: 178 print "%s:" % stat.name 179 disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", 180 "SAMP", "CV") 181 disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10]) 182 183 #loop through all the selected runs 184 for run in runs: 185 runTicks = source.retTicks([ run ]) 186 #throw away the first one, it's 0 187 runTicks.pop(0) 188 source.ticks = runTicks 189 avg = 0 190 stdev = 0 191 numoutsideavg = 0 192 numoutside1std = 0 193 numoutside2std = 0 194 pairRunTicks = [] 195 if value(stat, run.run) == 1e300*1e300: 196 continue 197 for t in range(0, len(runTicks)-(merge-1), merge): 198 tempPair = [] 199 for p in range(0,merge): 200 tempPair.append(runTicks[t+p]) 201 pairRunTicks.append(tempPair) 202 #loop through all the various ticks for each run 203 for tick in pairRunTicks: 204 source.ticks = tick 205 avg += value(stat, run.run) 206 avg /= len(pairRunTicks) 207 for tick in pairRunTicks: 208 source.ticks = tick 209 val = value(stat, run.run) 210 stdev += pow((val-avg),2) 211 stdev = math.sqrt(stdev / len(pairRunTicks)) 212 for tick in pairRunTicks: 213 source.ticks = tick 214 val = value(stat, run.run) 215 if (val < (avg * .9)) or (val > (avg * 1.1)): 216 numoutsideavg += 1 217 if (val < (avg - stdev)) or (val > (avg + stdev)): 218 numoutside1std += 1 219 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))): 220 numoutside2std += 1 221 if avg > 1000: 222 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 223 "%d" % numoutsideavg, "%d" % numoutside1std, 224 "%d" % numoutside2std, "%d" % len(pairRunTicks), 225 "%.3f" % (stdev/avg*100)) 226 elif avg > 100: 227 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 228 "%d" % numoutsideavg, "%d" % numoutside1std, 229 "%d" % numoutside2std, "%d" % len(pairRunTicks), 230 "%.5f" % (stdev/avg*100)) 231 else: 232 disp(run.name, "%.5f" % avg, "%.5f" % stdev, 233 "%d" % numoutsideavg, "%d" % numoutside1std, 234 "%d" % numoutside2std, "%d" % len(pairRunTicks), 235 "%.7f" % (stdev/avg*100)) 236 return 237 238 if command == 'all': 239 if len(args): 240 raise CommandException 241 242 all = [ 'bps', 'misses', 'mpkb', 'ipkb', 'pps', 'bpt' ] 243 for command in all: 244 commands(options, command, args) 245 246 if options.ticks: 247 if not options.graph: 248 print 'only displaying sample %s' % options.ticks 249 source.ticks = [ int(x) for x in options.ticks.split() ] 250 251 from output import StatOutput 252 output = StatOutput(options.jobfile, source) 253 output.xlabel = 'System Configuration' 254 output.colormap = 'RdYlGn' 255 256 if command == 'stat' or command == 'formula': 257 if len(args) != 1: 258 raise CommandException 259 260 if command == 'stat': 261 stats = source.getStat(args[0]) 262 if command == 'formula': 263 stats = eval(args[0]) 264 265 for stat in stats: 266 output.stat = stat 267 output.ylabel = stat.name 268 if options.graph: 269 output.graph(stat.name, options.graphdir) 270 else: 271 output.display(stat.name, options.printmode) 272 273 return 274 275 if len(args): 276 raise CommandException 277 278 from info import ProxyGroup 279 proxy = ProxyGroup(system = source[options.system]) 280 system = proxy.system 281 282 etherdev = system.tsunami.etherdev0 283 bytes = etherdev.rxBytes + etherdev.txBytes 284 kbytes = bytes / 1024 285 packets = etherdev.rxPackets + etherdev.txPackets 286 287 def display(): 288 if options.graph: 289 output.graph(command, options.graphdir, proxy) 290 else: 291 output.display(command, options.printmode) 292 293 if command == 'ticks': 294 output.stat = system.run0.numCycles 295 296 display() 297 return 298 299 if command == 'bytes': 300 output.stat = bytes 301 display() 302 return 303 304 if command == 'packets': 305 output.stat = packets 306 display() 307 return 308 309 if command == 'ppt' or command == 'tpp': 310 output.stat = packets / system.run0.numCycles 311 output.invert = command == 'tpp' 312 display() 313 return 314 315 if command == 'pps': 316 output.stat = packets / source['sim_seconds'] 317 output.ylabel = 'Packets/s' 318 display() 319 return 320 321 if command == 'bpt' or command == 'tpb': 322 output.stat = bytes / system.run0.numCycles * 8 323 output.ylabel = 'bps / Hz' 324 output.invert = command == 'tpb' 325 display() 326 return 327 328 if command in ('rxbps', 'txbps', 'bps'): 329 if command == 'rxbps': 330 output.stat = etherdev.rxBandwidth / 1e9 331 if command == 'txbps': 332 output.stat = etherdev.txBandwidth / 1e9 333 if command == 'bps': 334 output.stat = (etherdev.rxBandwidth + etherdev.txBandwidth) / 1e9 335 336 output.ylabel = 'Bandwidth (Gbps)' 337 output.ylim = [ 0.0, 10.0 ] 338 display() 339 return 340 341 if command == 'bpp': 342 output.stat = bytes / packets 343 output.ylabel = 'Bytes / Packet' 344 display() 345 return 346 347 if command == 'rxbpp': 348 output.stat = etherdev.rxBytes / etherdev.rxPackets 349 output.ylabel = 'Receive Bytes / Packet' 350 display() 351 return 352 353 if command == 'txbpp': 354 output.stat = etherdev.txBytes / etherdev.txPackets 355 output.ylabel = 'Transmit Bytes / Packet' 356 display() 357 return 358 359 if command == 'rtp': 360 output.stat = etherdev.rxPackets / etherdev.txPackets 361 output.ylabel = 'rxPackets / txPackets' 362 display() 363 return 364 365 if command == 'rtb': 366 output.stat = etherdev.rxBytes / etherdev.txBytes 367 output.ylabel = 'rxBytes / txBytes' 368 display() 369 return 370 371 misses = system.l2.overall_mshr_misses 372 373 if command == 'misses': 374 output.stat = misses 375 output.ylabel = 'Overall MSHR Misses' 376 display() 377 return 378 379 if command == 'mpkb': 380 output.stat = misses / (bytes / 1024) 381 output.ylabel = 'Misses / KB' 382 display() 383 return 384 385 if command == 'ipkb': 386 interrupts = system.run0.kern.faults[4] 387 output.stat = interrupts / kbytes 388 output.ylabel = 'Interrupts / KB' 389 display() 390 return 391 392 if command == 'execute': 393 output.stat = system.run0.ISSUE__count 394 display() 395 return 396 397 if command == 'commit': 398 output.stat = system.run0.COM__count 399 display() 400 return 401 402 if command == 'fetch': 403 output.stat = system.run0.FETCH__count 404 display() 405 return 406 407 raise CommandException 408 409 410class Options: pass 411 412if __name__ == '__main__': 413 import getpass 414 from jobfile import JobFile 415 416 options = Options() 417 options.host = None 418 options.db = None 419 options.passwd = '' 420 options.user = getpass.getuser() 421 options.runs = None 422 options.system = 'client' 423 options.method = None 424 options.graph = False 425 options.ticks = False 426 options.printmode = 'G' 427 jobfilename = 'Test.py' 428 options.jobfile = None 429 options.all = False 430 431 opts, args = getopts(sys.argv[1:], '-EFJad:g:h:j:m:pr:s:u:T:') 432 for o,a in opts: 433 if o == '-E': 434 options.printmode = 'E' 435 if o == '-F': 436 options.printmode = 'F' 437 if o == '-a': 438 options.all = True 439 if o == '-d': 440 options.db = a 441 if o == '-g': 442 options.graph = True; 443 options.graphdir = a 444 if o == '-h': 445 options.host = a 446 if o == '-J': 447 jobfilename = None 448 if o == '-j': 449 jobfilename = a 450 if o == '-m': 451 options.method = a 452 if o == '-p': 453 options.passwd = getpass.getpass() 454 if o == '-r': 455 options.runs = a 456 if o == '-u': 457 options.user = a 458 if o == '-s': 459 options.system = a 460 if o == '-T': 461 options.ticks = a 462 463 if jobfilename: 464 options.jobfile = JobFile(jobfilename) 465 if not options.host: 466 options.host = options.jobfile.dbhost 467 if not options.db: 468 options.db = options.jobfile.statdb 469 470 if not options.host: 471 sys.exit('Database server must be provided from a jobfile or -h') 472 473 if not options.db: 474 sys.exit('Database name must be provided from a jobfile or -d') 475 476 if len(args) == 0: 477 usage() 478 479 command = args[0] 480 args = args[1:] 481 482 try: 483 commands(options, command, args) 484 except CommandException: 485 usage() 486