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 bins [regex] List bins (only matching regex)
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
143 if command == 'bins':
144 if len(args) == 0:
145 source.listBins()
146 elif len(args) == 1:
147 source.listBins(args[0])
148 else:
149 raise CommandException
150
151 return
152
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:
282 output.display(stat.name, options.binned, options.printmode)
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:
302 output.display(command, options.binned, options.printmode)
291 output.display(command, options.printmode)
292
304 if command == 'usertime':
305 import copy
306 user = copy.copy(system.run0.numCycles)
307 user.bins = 'user'
308
309 output.stat = user / system.run0.numCycles
310 output.ylabel = 'User Fraction'
311
312 display()
313 return
314
293 if command == 'ticks':
294 output.stat = system.run0.numCycles
317 output.binstats = [ 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)
404 output.binstats = [ misses ]
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
412 output.binstats = [ interrupts ]
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
449 options.binned = False
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
457 opts, args = getopts(sys.argv[1:], '-BEFJad:g:h:j:m:pr:s:u:T:')
431 opts, args = getopts(sys.argv[1:], '-EFJad:g:h:j:m:pr:s:u:T:')
432 for o,a in opts:
459 if o == '-B':
460 options.binned = True
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()