stats.py revision 1331:a0b8619e0e72
1#!/usr/bin/env python
2from __future__ import division
3import re, sys, math
4
5
6def usage():
7    print '''\
8Usage: %s [-E] [-F] [-d <db> ] [-g <get> ] [-h <host>] [-p]
9       [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>]
10       <command> [command args]
11
12       commands    extra parameters   description
13       ----------- ------------------ ---------------------------------------
14       bins        [regex]            List bins (only matching regex)
15       formula     <formula>          Evaluated formula specified
16       formulas    [regex]            List formulas (only matching regex)
17       runs        none               List all runs in database
18       samples     none               List samples present in database
19       stability   <pairnum> <stats>  Calculated statistical info about stats
20       stat        <regex>            Show stat data (only matching regex)
21       stats       [regex]            List all stats (only matching regex)
22''' % sys.argv[0]
23    sys.exit(1)
24
25def getopts(list, flags):
26    import getopt
27    try:
28        opts, args = getopt.getopt(list, flags)
29    except getopt.GetoptError:
30        usage()
31
32    return opts, args
33
34def printval(name, value, invert = False):
35    if invert and value != 0.0:
36        value = 1 / value
37
38    if value == (1e300*1e300):
39        return
40
41    if printval.mode == 'G':
42        print '%s:    %g' % (name, value)
43    elif printval.mode != 'F' and value > 1e6:
44        print '%s:    %0.5e' % (name, value)
45    else:
46        print '%s:    %f' % (name, value)
47
48printval.mode = 'G'
49
50def unique(list):
51    set = {}
52    map(set.__setitem__, list, [])
53    return set.keys()
54
55def graphdata68(runs, options, tag, label, value):
56    import info
57    configs = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ]
58    benchmarks = [ 'm', 's', 'snt', 'nb1', 'w1', 'w2', 'w3', 'w4', 'nm', 'ns', 'nw1', 'nw2', 'nw3' ]
59    dmas = [ 'x' ]
60    caches = [ '2', '4' ]
61
62    names = []
63
64    bench_system = {
65        'm' : 'client',
66        's' : 'client',
67        'snt' : 'client',
68        'nb1' : 'server',
69        'nb2' : 'server',
70        'nt1' : 'server',
71        'nt2' : 'server',
72        'w1' : 'server',
73        'w2' : 'server',
74        'w3' : 'server',
75        'w4' : 'server',
76        'w1s' : 'server',
77        'w2s' : 'server',
78        'w3s' : 'server',
79        'ns' : 'natbox',
80        'nm' : 'natbox',
81        'nw1' : 'natbox',
82        'nw2' : 'natbox',
83        'nw3' : 'natbox'
84        }
85
86    for bench in benchmarks:
87        if bench_system[bench] != options.system:
88            continue
89
90        for dma in dmas:
91            for cache in caches:
92                    names.append([bench, dma, cache])
93
94    for bench,dma,cache in names:
95        base = '%s.%s.%s' % (bench, dma, cache)
96        fname = 'data/%s.%s.68.dat' % (tag, base)
97        f = open(fname, 'w')
98        print >>f, '#set TITLE = '
99        print >>f, '#set ylbl = %s' % label
100        #print >>f, '#set sublabels = %s' % ' '.join(configs)
101        print >>f, '#set sublabels = ste hte htd ocm occ ocs'
102
103        for speed,freq in zip(['s', '6', '8', 'q'],['4GHz', '6GHz','8GHz', '10GHz']):
104            print >>f, '"%s"' % freq,
105            for conf in configs:
106                name = '%s.%s.%s.%s.%s' % (conf, bench, dma, cache, speed)
107                run = info.source.allRunNames[name]
108                info.display_run = run.run;
109                val = float(value)
110                if val == 1e300*1e300:
111                    print >>f, 0.0,
112                else:
113                    print >>f, "%f" % val,
114            print >>f
115        f.close()
116
117def graphdata(runs, options, tag, label, value):
118    if options.graph68:
119        graphdata68(runs, options, tag, label, value)
120        return
121
122    import info
123    configs = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp' ]
124    #benchmarks = [ 'm', 's', 'nb1', 'nb2', 'nt1', 'nt2', 'w1', 'w2', 'w3', 'w4', 'ns', 'nm', 'nw1', 'nw2', 'nw3' ]
125    #benchmarks = [ 'm', 's', 'nb1', 'nb2', 'nt1', 'w1', 'w2', 'w3', 'ns', 'nm', 'w1s' ]
126    benchmarks = [ 'm', 's', 'nb1', 'nb2', 'w1', 'w2', 'w3', 'w4', 'ns', 'nm', 'nw1', 'snt' ]
127    #dmas = [ 'x', 'd', 'b' ]
128    dmas = [ 'x' ]
129    caches = [ '2', '4' ]
130
131    names = []
132
133    bench_system = {
134        'm' : 'client',
135        's' : 'client',
136        'snt' : 'client',
137        'nb1' : 'server',
138        'nb2' : 'server',
139        'nt1' : 'server',
140        'nt2' : 'server',
141        'w1' : 'server',
142        'w2' : 'server',
143        'w3' : 'server',
144        'w4' : 'server',
145        'w1s' : 'server',
146        'w2s' : 'server',
147        'w3s' : 'server',
148        'ns' : 'natbox',
149        'nm' : 'natbox',
150        'nw1' : 'natbox',
151        'nw2' : 'natbox',
152        'nw3' : 'natbox'
153        }
154
155    for bench in benchmarks:
156        if bench_system[bench] != options.system:
157            continue
158
159        for dma in dmas:
160            for cache in caches:
161                    names.append([bench, dma, cache])
162
163    for bench,dma,cache in names:
164        base = '%s.%s.%s' % (bench, dma, cache)
165        fname = 'data/%s.%s.dat' % (tag, base)
166        f = open(fname, 'w')
167        print >>f, '#set TITLE = '
168        print >>f, '#set ylbl = %s' % label
169        #print >>f, '#set sublabels = %s' % ' '.join(configs)
170        print >>f, '#set sublabels = ste hte htd ocm occ ocs'
171
172        for speed,freq in zip(['s', 'q'],['4GHz','10GHz']):
173            print >>f, '"%s"' % freq,
174            for conf in configs:
175                name = '%s.%s.%s.%s.%s' % (conf, bench, dma, cache, speed)
176                run = info.source.allRunNames[name]
177                info.display_run = run.run;
178                val = float(value)
179                if val == 1e300*1e300:
180                    print >>f, 0.0,
181                else:
182                    print >>f, "%f" % val,
183            print >>f
184        f.close()
185
186def printdata(runs, value, invert = False):
187    import info
188    for run in runs:
189        info.display_run = run.run;
190        val = float(value)
191        printval(run.name, val)
192
193class CommandException(Exception):
194    pass
195
196def commands(options, command, args):
197    if command == 'database':
198        if len(args) == 0: raise CommandException
199
200        import dbinit
201        mydb = dbinit.MyDB(options)
202
203        if args[0] == 'drop':
204            if len(args) > 2: raise CommandException
205            mydb.admin()
206            mydb.drop()
207            if len(args) == 2 and args[1] == 'init':
208                mydb.create()
209                mydb.connect()
210                mydb.populate()
211            mydb.close()
212            return
213
214        if args[0] == 'init':
215            if len(args) > 1: raise CommandException
216            mydb.admin()
217            mydb.create()
218            mydb.connect()
219            mydb.populate()
220            mydb.close()
221            return
222
223        if args[0] == 'clean':
224            if len(args) > 1: raise CommandException
225            mydb.connect()
226            mydb.clean()
227            return
228
229        raise CommandException
230
231    import db, info
232    info.source = db.Database()
233    info.source.host = options.host
234    info.source.db = options.db
235    info.source.passwd = options.passwd
236    info.source.user = options.user
237    info.source.connect()
238    info.source.update_dict(globals())
239
240    if type(options.get) is str:
241        info.source.get = options.get
242
243    if options.runs is None:
244        runs = info.source.allRuns
245    else:
246        rx = re.compile(options.runs)
247        runs = []
248        for run in info.source.allRuns:
249            if rx.match(run.name):
250                runs.append(run)
251
252    info.display_run = runs[0].run
253
254    if command == 'runs':
255        user = None
256        opts, args = getopts(args, '-u')
257        if len(args):
258            raise CommandException
259        for o,a in opts:
260            if o == '-u':
261                user = a
262        info.source.listRuns(user)
263        return
264
265    if command == 'stability':
266        if len(args) < 2:
267            raise CommandException
268
269        try:
270            merge = int(args[0])
271        except ValueError:
272            usage()
273        stats = info.source.getStat(args[1])
274        info.source.get = "sum"
275
276
277        #loop through all the stats selected
278        for stat in stats:
279
280            print "%s:" % stat.name
281            print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
282                  ("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", "SAMP", "CV")
283            print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
284                  ("--------------------", "------------",
285                   "------------", "----", "-----", "-----", "-----", "----------")
286            #loop through all the selected runs
287            for run in runs:
288                info.display_run = run.run;
289                runTicks = info.source.retTicks([ run ])
290                #throw away the first one, it's 0
291                runTicks.pop(0)
292                info.globalTicks = runTicks
293                avg = 0
294                stdev = 0
295                numoutsideavg  = 0
296                numoutside1std = 0
297                numoutside2std = 0
298                pairRunTicks = []
299                if float(stat) == 1e300*1e300:
300                    continue
301                for t in range(0, len(runTicks)-(merge-1), merge):
302                    tempPair = []
303                    for p in range(0,merge):
304                        tempPair.append(runTicks[t+p])
305                    pairRunTicks.append(tempPair)
306                #loop through all the various ticks for each run
307                for tick in pairRunTicks:
308                    info.globalTicks = tick
309                    avg += float(stat)
310                avg /= len(pairRunTicks)
311                for tick in pairRunTicks:
312                    info.globalTicks = tick
313                    val = float(stat)
314                    stdev += pow((val-avg),2)
315                stdev = math.sqrt(stdev / len(pairRunTicks))
316                for tick in pairRunTicks:
317                    info.globalTicks = tick
318                    val = float(stat)
319                    if (val < (avg * .9)) or (val > (avg * 1.1)):
320                        numoutsideavg += 1
321                    if (val < (avg - stdev)) or (val > (avg + stdev)):
322                        numoutside1std += 1
323                    if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))):
324                        numoutside2std += 1
325                if avg > 1000:
326                    print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
327                          (run.name, "%.1f" % avg, "%.1f" % stdev,
328                           "%d" % numoutsideavg, "%d" % numoutside1std,
329                           "%d" % numoutside2std, "%d" % len(pairRunTicks),
330                           "%.3f" % (stdev/avg*100))
331                elif avg > 100:
332                    print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
333                          (run.name, "%.1f" % avg, "%.1f" % stdev,
334                           "%d" % numoutsideavg, "%d" % numoutside1std,
335                           "%d" % numoutside2std, "%d" % len(pairRunTicks),
336                           "%.5f" % (stdev/avg*100))
337                else:
338                    print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
339                          (run.name, "%.5f" % avg, "%.5f" % stdev,
340                           "%d" % numoutsideavg, "%d" % numoutside1std,
341                           "%d" % numoutside2std, "%d" % len(pairRunTicks),
342                           "%.7f" % (stdev/avg*100))
343        return
344
345    if command == 'stats':
346        if len(args) == 0:
347            info.source.listStats()
348        elif len(args) == 1:
349            info.source.listStats(args[0])
350        else:
351            raise CommandException
352
353        return
354
355    if command == 'stat':
356        if len(args) != 1:
357            raise CommandException
358
359        stats = info.source.getStat(args[0])
360        for stat in stats:
361            if options.graph:
362                graphdata(runs, options, stat.name, stat.name, stat)
363            else:
364                if options.ticks:
365                   print 'only displaying sample %s' % options.ticks
366                   info.globalTicks = [ int(x) for x in options.ticks.split() ]
367
368                if options.binned:
369                    print 'kernel ticks'
370                    stat.bins = 'kernel'
371                    printdata(runs, stat)
372
373                    print 'idle ticks'
374                    stat.bins = 'idle'
375                    printdata(runs, stat)
376
377                    print 'user ticks'
378                    stat.bins = 'user'
379                    printdata(runs, stat)
380
381                    print 'interrupt ticks'
382                    stat.bins = 'interrupt'
383                    printdata(runs, stat)
384
385                    print 'total ticks'
386
387                stat.bins = None
388                print stat.name
389                printdata(runs, stat)
390        return
391
392    if command == 'formula':
393        if len(args) != 1:
394            raise CommandException
395
396        stats = eval(args[0])
397        for stat in stats:
398            if options.graph:
399                graphdata(runs, options, stat.name, stat.name, stat)
400            else:
401                if options.binned:
402                    print 'kernel ticks'
403                    stat.bins = 'kernel'
404                    printdata(runs, stat)
405
406                    print 'idle ticks'
407                    stat.bins = 'idle'
408                    printdata(runs, stat)
409
410                    print 'user ticks'
411                    stat.bins = 'user'
412                    printdata(runs, stat)
413
414                    print 'interrupt ticks'
415                    stat.bins = 'interrupt'
416                    printdata(runs, stat)
417
418                    print 'total ticks'
419
420                stat.bins = None
421                print args[0]
422                printdata(runs, stat)
423        return
424
425    if command == 'bins':
426        if len(args) == 0:
427            info.source.listBins()
428        elif len(args) == 1:
429            info.source.listBins(args[0])
430        else:
431            raise CommandException
432
433        return
434
435    if command == 'formulas':
436        if len(args) == 0:
437            info.source.listFormulas()
438        elif len(args) == 1:
439            info.source.listFormulas(args[0])
440        else:
441            raise CommandException
442
443        return
444
445    if command == 'samples':
446        if len(args):
447            raise CommandException
448
449        info.source.listTicks(runs)
450        return
451
452    if len(args):
453        raise CommandException
454
455    system = info.source.__dict__[options.system]
456
457    if command == 'usertime':
458        import copy
459        kernel = copy.copy(system.full_cpu.numCycles)
460        kernel.bins = 'kernel'
461
462        user = copy.copy(system.full_cpu.numCycles)
463        user.bins = 'user'
464
465        if options.graph:
466            graphdata(runs, options, 'usertime', 'User Fraction',
467                      user / system.full_cpu.numCycles)
468        else:
469            printdata(runs, user / system.full_cpu.numCycles)
470        return
471
472    if command == 'ticks':
473        if options.binned:
474            print 'kernel ticks'
475            system.full_cpu.numCycles.bins = 'kernel'
476            printdata(runs, system.full_cpu.numCycles)
477
478            print 'idle ticks'
479            system.full_cpu.numCycles.bins = 'idle'
480            printdata(runs, system.full_cpu.numCycles)
481
482            print 'user ticks'
483            system.full_cpu.numCycles.bins = 'user'
484            printdata(runs, system.full_cpu.numCycles)
485
486            print 'total ticks'
487
488        system.full_cpu.numCycles.bins = None
489        printdata(runs, system.full_cpu.numCycles)
490        return
491
492    if command == 'packets':
493        packets = system.tsunami.etherdev.rxPackets
494        if options.graph:
495            graphdata(runs, options, 'packets', 'Packets', packets)
496        else:
497            printdata(runs, packets)
498        return
499
500    if command == 'ppt' or command == 'tpp':
501        ppt = system.tsunami.etherdev.rxPackets / sim_ticks
502        printdata(runs, ppt, command == 'tpp')
503        return
504
505    if command == 'pps':
506        pps = system.tsunami.etherdev.rxPackets / sim_seconds
507        if options.graph:
508            graphdata(runs, options, 'pps', 'Packets/s', pps)
509        else:
510            printdata(runs, pps)
511        return
512
513    if command == 'bpt' or command == 'tpb':
514        bytes = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
515        bpt = bytes / sim_ticks * 8
516        if options.graph:
517            graphdata(runs, options, 'bpt', 'bps / Hz', bpt)
518        else:
519            printdata(runs, bpt, command == 'tpb')
520        return
521
522    if command == 'bptb' or command == 'tpbb':
523        bytes = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
524
525        print 'kernel stats'
526        bytes.bins = 'kernel'
527        printdata(runs, bytes / ticks)
528
529        print 'idle stats'
530        bytes.bins = 'idle'
531        printdata(runs, bytes / ticks)
532
533        print 'user stats'
534        bytes.bins = 'user'
535        printdata(runs, bytes / ticks)
536
537        return
538
539    if command == 'bytes':
540        stat = system.tsunami.etherdev.rxBytes + system.tsunami.etherdev.txBytes
541
542        if options.binned:
543            print '%s kernel stats' % stat.name
544            stat.bins = 'kernel'
545            printdata(runs, stat)
546
547            print '%s idle stats' % stat.name
548            stat.bins = 'idle'
549            printdata(runs, stat)
550
551            print '%s user stats' % stat.name
552            stat.bins = 'user'
553            printdata(runs, stat)
554
555            print '%s total stats' % stat.name
556            stat.bins = None
557
558        printdata(runs, stat)
559        return
560
561    if command == 'rxbps':
562        gbps = system.tsunami.etherdev.rxBandwidth / 1e9
563        if options.graph:
564            graphdata(runs, options, 'rxbps', 'Bandwidth (Gbps)',  gbps)
565        else:
566            printdata(runs, gbps)
567        return
568
569    if command == 'txbps':
570        gbps = system.tsunami.etherdev.txBandwidth / 1e9
571        if options.graph:
572            graphdata(runs, options, 'txbps', 'Bandwidth (Gbps)',  gbps)
573        else:
574            printdata(runs, gbps)
575        return
576
577    if command == 'bps':
578        rxbps = system.tsunami.etherdev.rxBandwidth
579        txbps = system.tsunami.etherdev.txBandwidth
580        gbps = (rxbps + txbps) / 1e9
581        if options.graph:
582            graphdata(runs, options, 'bps', 'Bandwidth (Gbps)',  gbps)
583        else:
584            printdata(runs, gbps)
585        return
586
587    if command == 'misses':
588        stat = system.L2.overall_mshr_misses
589        if options.binned:
590            print '%s kernel stats' % stat.name
591            stat.bins = 'kernel'
592            printdata(runs, stat)
593
594            print '%s idle stats' % stat.name
595            stat.bins = 'idle'
596            printdata(runs, stat)
597
598            print '%s user stats' % stat.name
599            stat.bins = 'user'
600            printdata(runs, stat)
601
602            print '%s total stats' % stat.name
603
604        stat.bins = None
605        if options.graph:
606            graphdata(runs, options, 'misses', 'Overall MSHR Misses', stat)
607        else:
608            printdata(runs, stat)
609        return
610
611    if command == 'mpkb':
612        misses = system.L2.overall_mshr_misses
613        rxbytes = system.tsunami.etherdev.rxBytes
614        txbytes = system.tsunami.etherdev.txBytes
615
616        if options.binned:
617            print 'mpkb kernel stats'
618            misses.bins = 'kernel'
619            mpkb = misses / ((rxbytes + txbytes) / 1024)
620            printdata(runs, mpkb)
621
622            print 'mpkb idle stats'
623            misses.bins = 'idle'
624            mpkb = misses / ((rxbytes + txbytes) / 1024)
625            printdata(runs, mpkb)
626
627            print 'mpkb user stats'
628            misses.bins = 'user'
629            mpkb = misses / ((rxbytes + txbytes) / 1024)
630            printdata(runs, mpkb)
631
632            print 'mpkb total stats'
633
634        mpkb = misses / ((rxbytes + txbytes) / 1024)
635        misses.bins = None
636        if options.graph:
637            graphdata(runs, options, 'mpkb', 'Misses / KB',  mpkb)
638        else:
639            printdata(runs, mpkb)
640        return
641
642    if command == 'ipkb':
643        interrupts = system.full_cpu.kern.faults[4]
644        rxbytes = system.tsunami.etherdev.rxBytes
645        txbytes = system.tsunami.etherdev.txBytes
646
647        if options.binned:
648            print 'ipkb kernel stats'
649            interrupts.bins = 'kernel'
650            ipkb = interrupts / ((rxbytes + txbytes) / 1024)
651            printdata(runs, ipkb)
652
653            print 'ipkb idle stats'
654            interrupts.bins = 'idle'
655            ipkb = interrupts / ((rxbytes + txbytes) / 1024)
656            printdata(runs, ipkb)
657
658            print 'ipkb user stats'
659            interrupts.bins = 'user'
660            ipkb = interrupts / ((rxbytes + txbytes) / 1024)
661            printdata(runs, ipkb)
662
663            print 'ipkb total stats'
664
665        ipkb = interrupts / ((rxbytes + txbytes) / 1024)
666        interrupts.bins = None
667        if options.graph:
668            graphdata(runs, options, 'ipkb', 'Interrupts / KB',  ipkb)
669        else:
670            printdata(runs, ipkb)
671        return
672
673    if command == 'execute':
674        printdata(runs, system.full_cpu.ISSUE__count)
675        return
676
677    if command == 'commit':
678        printdata(runs, system.full_cpu.COM__count)
679        return
680
681    if command == 'fetch':
682        printdata(runs, system.full_cpu.FETCH__count)
683        return
684
685    if command == 'bpp':
686        ed = system.tsunami.etherdev
687        bpp = (ed.rxBytes + ed.txBytes) / (ed.rxPackets + ed.txPackets)
688        if options.graph:
689            graphdata(runs, options, 'bpp', 'Bytes / Packet',  bpp)
690        else:
691            printdata(runs, bpp)
692        return
693
694    if command == 'rxbpp':
695        bpp = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.rxPackets
696        if options.graph:
697            graphdata(runs, options, 'rxbpp', 'Receive Bytes / Packet',  bpp)
698        else:
699            printdata(runs, bpp)
700        return
701
702    if command == 'txbpp':
703        bpp = system.tsunami.etherdev.txBytes / system.tsunami.etherdev.txPackets
704        if options.graph:
705            graphdata(runs, options, 'txbpp', 'Transmit Bytes / Packet',  bpp)
706        else:
707            printdata(runs, bpp)
708        return
709
710    if command == 'rtp':
711        rtp = system.tsunami.etherdev.rxPackets / system.tsunami.etherdev.txPackets
712        if options.graph:
713            graphdata(runs, options, 'rtp', 'rxPackets / txPackets',  rtp)
714        else:
715            printdata(runs, rtp)
716        return
717
718    if command == 'rtb':
719        rtb = system.tsunami.etherdev.rxBytes / system.tsunami.etherdev.txBytes
720        if options.graph:
721            graphdata(runs, options, 'rtb', 'rxBytes / txBytes',  rtb)
722        else:
723            printdata(runs, rtb)
724        return
725
726    raise CommandException
727
728
729class Options: pass
730
731if __name__ == '__main__':
732    import getpass
733
734    options = Options()
735    options.host = 'zizzer.pool'
736    options.db = None
737    options.passwd = ''
738    options.user = getpass.getuser()
739    options.runs = None
740    options.system = 'client'
741    options.get = None
742    options.binned = False
743    options.graph = False
744    options.graph68 = False
745    options.ticks = False
746
747    opts, args = getopts(sys.argv[1:], '-6BEFGd:g:h:pr:s:u:T:')
748    for o,a in opts:
749        if o == '-6':
750            options.graph68 = True
751        if o == '-B':
752            options.binned = True
753        if o == '-E':
754            printval.mode = 'E'
755        if o == '-F':
756            printval.mode = 'F'
757        if o == '-G':
758            options.graph = True;
759        if o == '-d':
760            options.db = a
761        if o == '-g':
762            options.get = a
763        if o == '-h':
764            options.host = a
765        if o == '-p':
766            options.passwd = getpass.getpass()
767        if o == '-r':
768            options.runs = a
769        if o == '-u':
770            options.user = a
771        if o == '-s':
772            options.system = a
773        if o == '-T':
774            options.ticks = a
775
776    if len(args) == 0:
777        usage()
778
779    command = args[0]
780    args = args[1:]
781
782    try:
783        commands(options, command, args)
784    except CommandException:
785        usage()
786