stats.py revision 13540
1#!/usr/bin/env python2.7 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# 29# Authors: Nathan Binkert 30 31import re, sys, math 32 33def usage(): 34 print '''\ 35Usage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p] 36 [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>] 37 <command> [command args] 38 39 commands extra parameters description 40 ----------- ------------------ --------------------------------------- 41 formula <formula> Evaluated formula specified 42 formulas [regex] List formulas (only matching regex) 43 runs none List all runs in database 44 samples none List samples present in database 45 stability <pairnum> <stats> Calculated statistical info about stats 46 stat <regex> Show stat data (only matching regex) 47 stats [regex] List all stats (only matching regex) 48 49 database <command> Where command is drop, init, or clean 50 51''' % sys.argv[0] 52 sys.exit(1) 53 54def getopts(list, flags): 55 import getopt 56 try: 57 opts, args = getopt.getopt(list, flags) 58 except getopt.GetoptError: 59 usage() 60 61 return opts, args 62 63class CommandException(Exception): 64 pass 65 66def commands(options, command, args): 67 if command == 'database': 68 if len(args) == 0: raise CommandException 69 70 import dbinit 71 mydb = dbinit.MyDB(options) 72 73 if args[0] == 'drop': 74 if len(args) > 2: raise CommandException 75 mydb.admin() 76 mydb.drop() 77 if len(args) == 2 and args[1] == 'init': 78 mydb.create() 79 mydb.connect() 80 mydb.populate() 81 mydb.close() 82 return 83 84 if args[0] == 'init': 85 if len(args) > 1: raise CommandException 86 mydb.admin() 87 mydb.create() 88 mydb.connect() 89 mydb.populate() 90 mydb.close() 91 return 92 93 if args[0] == 'clean': 94 if len(args) > 1: raise CommandException 95 mydb.connect() 96 mydb.clean() 97 return 98 99 raise CommandException 100 101 import db 102 source = db.Database() 103 source.host = options.host 104 source.db = options.db 105 source.passwd = options.passwd 106 source.user = options.user 107 source.connect() 108 #source.update_dict(globals()) 109 110 if type(options.method) is str: 111 source.method = options.method 112 113 if options.runs is None: 114 runs = source.allRuns 115 else: 116 rx = re.compile(options.runs) 117 runs = [] 118 for run in source.allRuns: 119 if rx.match(run.name): 120 runs.append(run) 121 122 if command == 'runs': 123 user = None 124 opts, args = getopts(args, '-u') 125 if len(args): 126 raise CommandException 127 for o,a in opts: 128 if o == '-u': 129 user = a 130 source.listRuns(user) 131 return 132 133 if command == 'stats': 134 if len(args) == 0: 135 source.listStats() 136 elif len(args) == 1: 137 source.listStats(args[0]) 138 else: 139 raise CommandException 140 141 return 142 143 if command == 'formulas': 144 if len(args) == 0: 145 source.listFormulas() 146 elif len(args) == 1: 147 source.listFormulas(args[0]) 148 else: 149 raise CommandException 150 151 return 152 153 if command == 'samples': 154 if len(args): 155 raise CommandException 156 157 source.listTicks(runs) 158 return 159 160 if command == 'stability': 161 if len(args) < 2: 162 raise CommandException 163 164 try: 165 merge = int(args[0]) 166 except ValueError: 167 usage() 168 stats = source.getStat(args[1]) 169 source.method = 'sum' 170 171 def disp(*args): 172 print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args 173 174 # temporary variable containing a bunch of dashes 175 d = '-' * 100 176 177 #loop through all the stats selected 178 for stat in stats: 179 print "%s:" % stat.name 180 disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", 181 "SAMP", "CV") 182 disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10]) 183 184 #loop through all the selected runs 185 for run in runs: 186 runTicks = source.retTicks([ run ]) 187 #throw away the first one, it's 0 188 runTicks.pop(0) 189 source.ticks = runTicks 190 avg = 0 191 stdev = 0 192 numoutsideavg = 0 193 numoutside1std = 0 194 numoutside2std = 0 195 pairRunTicks = [] 196 if value(stat, run.run) == 1e300*1e300: 197 continue 198 for t in range(0, len(runTicks)-(merge-1), merge): 199 tempPair = [] 200 for p in range(0,merge): 201 tempPair.append(runTicks[t+p]) 202 pairRunTicks.append(tempPair) 203 #loop through all the various ticks for each run 204 for tick in pairRunTicks: 205 source.ticks = tick 206 avg += value(stat, run.run) 207 avg /= len(pairRunTicks) 208 for tick in pairRunTicks: 209 source.ticks = tick 210 val = value(stat, run.run) 211 stdev += pow((val-avg),2) 212 stdev = math.sqrt(stdev / len(pairRunTicks)) 213 for tick in pairRunTicks: 214 source.ticks = tick 215 val = value(stat, run.run) 216 if (val < (avg * .9)) or (val > (avg * 1.1)): 217 numoutsideavg += 1 218 if (val < (avg - stdev)) or (val > (avg + stdev)): 219 numoutside1std += 1 220 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))): 221 numoutside2std += 1 222 if avg > 1000: 223 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 224 "%d" % numoutsideavg, "%d" % numoutside1std, 225 "%d" % numoutside2std, "%d" % len(pairRunTicks), 226 "%.3f" % (stdev/avg*100)) 227 elif avg > 100: 228 disp(run.name, "%.1f" % avg, "%.1f" % stdev, 229 "%d" % numoutsideavg, "%d" % numoutside1std, 230 "%d" % numoutside2std, "%d" % len(pairRunTicks), 231 "%.5f" % (stdev/avg*100)) 232 else: 233 disp(run.name, "%.5f" % avg, "%.5f" % stdev, 234 "%d" % numoutsideavg, "%d" % numoutside1std, 235 "%d" % numoutside2std, "%d" % len(pairRunTicks), 236 "%.7f" % (stdev/avg*100)) 237 return 238 239 if command == 'all': 240 if len(args): 241 raise CommandException 242 243 all = [ 'bps', 'misses', 'mpkb', 'ipkb', 'pps', 'bpt' ] 244 for command in all: 245 commands(options, command, args) 246 247 if options.ticks: 248 if not options.graph: 249 print 'only displaying sample %s' % options.ticks 250 source.ticks = [ int(x) for x in options.ticks.split() ] 251 252 from output import StatOutput 253 output = StatOutput(options.jobfile, source) 254 output.xlabel = 'System Configuration' 255 output.colormap = 'RdYlGn' 256 257 if command == 'stat' or command == 'formula': 258 if len(args) != 1: 259 raise CommandException 260 261 if command == 'stat': 262 stats = source.getStat(args[0]) 263 if command == 'formula': 264 stats = eval(args[0]) 265 266 for stat in stats: 267 output.stat = stat 268 output.ylabel = stat.name 269 if options.graph: 270 output.graph(stat.name, options.graphdir) 271 else: 272 output.display(stat.name, options.printmode) 273 274 return 275 276 if len(args): 277 raise CommandException 278 279 from info import ProxyGroup 280 proxy = ProxyGroup(system = source[options.system]) 281 system = proxy.system 282 283 etherdev = system.tsunami.etherdev0 284 bytes = etherdev.rxBytes + etherdev.txBytes 285 kbytes = bytes / 1024 286 packets = etherdev.rxPackets + etherdev.txPackets 287 288 def display(): 289 if options.graph: 290 output.graph(command, options.graphdir, proxy) 291 else: 292 output.display(command, options.printmode) 293 294 if command == 'ticks': 295 output.stat = system.run0.numCycles 296 297 display() 298 return 299 300 if command == 'bytes': 301 output.stat = bytes 302 display() 303 return 304 305 if command == 'packets': 306 output.stat = packets 307 display() 308 return 309 310 if command == 'ppt' or command == 'tpp': 311 output.stat = packets / system.run0.numCycles 312 output.invert = command == 'tpp' 313 display() 314 return 315 316 if command == 'pps': 317 output.stat = packets / source['sim_seconds'] 318 output.ylabel = 'Packets/s' 319 display() 320 return 321 322 if command == 'bpt' or command == 'tpb': 323 output.stat = bytes / system.run0.numCycles * 8 324 output.ylabel = 'bps / Hz' 325 output.invert = command == 'tpb' 326 display() 327 return 328 329 if command in ('rxbps', 'txbps', 'bps'): 330 if command == 'rxbps': 331 output.stat = etherdev.rxBandwidth / 1e9 332 if command == 'txbps': 333 output.stat = etherdev.txBandwidth / 1e9 334 if command == 'bps': 335 output.stat = (etherdev.rxBandwidth + etherdev.txBandwidth) / 1e9 336 337 output.ylabel = 'Bandwidth (Gbps)' 338 output.ylim = [ 0.0, 10.0 ] 339 display() 340 return 341 342 if command == 'bpp': 343 output.stat = bytes / packets 344 output.ylabel = 'Bytes / Packet' 345 display() 346 return 347 348 if command == 'rxbpp': 349 output.stat = etherdev.rxBytes / etherdev.rxPackets 350 output.ylabel = 'Receive Bytes / Packet' 351 display() 352 return 353 354 if command == 'txbpp': 355 output.stat = etherdev.txBytes / etherdev.txPackets 356 output.ylabel = 'Transmit Bytes / Packet' 357 display() 358 return 359 360 if command == 'rtp': 361 output.stat = etherdev.rxPackets / etherdev.txPackets 362 output.ylabel = 'rxPackets / txPackets' 363 display() 364 return 365 366 if command == 'rtb': 367 output.stat = etherdev.rxBytes / etherdev.txBytes 368 output.ylabel = 'rxBytes / txBytes' 369 display() 370 return 371 372 misses = system.l2.overall_mshr_misses 373 374 if command == 'misses': 375 output.stat = misses 376 output.ylabel = 'Overall MSHR Misses' 377 display() 378 return 379 380 if command == 'mpkb': 381 output.stat = misses / (bytes / 1024) 382 output.ylabel = 'Misses / KB' 383 display() 384 return 385 386 if command == 'ipkb': 387 interrupts = system.run0.kern.faults[4] 388 output.stat = interrupts / kbytes 389 output.ylabel = 'Interrupts / KB' 390 display() 391 return 392 393 if command == 'execute': 394 output.stat = system.run0.ISSUE__count 395 display() 396 return 397 398 if command == 'commit': 399 output.stat = system.run0.COM__count 400 display() 401 return 402 403 if command == 'fetch': 404 output.stat = system.run0.FETCH__count 405 display() 406 return 407 408 raise CommandException 409 410 411class Options: pass 412 413if __name__ == '__main__': 414 import getpass 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 = None 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 from jobfile import JobFile 465 options.jobfile = JobFile(jobfilename) 466 if not options.host: 467 options.host = options.jobfile.dbhost 468 if not options.db: 469 options.db = options.jobfile.statdb 470 471 if not options.host: 472 sys.exit('Database server must be provided from a jobfile or -h') 473 474 if not options.db: 475 sys.exit('Database name must be provided from a jobfile or -d') 476 477 if len(args) == 0: 478 usage() 479 480 command = args[0] 481 args = args[1:] 482 483 try: 484 commands(options, command, args) 485 except CommandException: 486 usage() 487