1'''
2Created on May 16, 2011
3
4@author: bungeman
5'''
6import sys
7import getopt
8import bench_util
9
10def usage():
11    """Prints simple usage information."""
12
13    print '-o <file> the old bench output file.'
14    print '-n <file> the new bench output file.'
15    print '-h causes headers to be output.'
16    print '-f <fieldSpec> which fields to output and in what order.'
17    print '   Not specifying is the same as -f "bctondp".'
18    print '  b: bench'
19    print '  c: config'
20    print '  t: time type'
21    print '  o: old time'
22    print '  n: new time'
23    print '  d: diff'
24    print '  p: percent diff'
25
26class BenchDiff:
27    """A compare between data points produced by bench.
28
29    (BenchDataPoint, BenchDataPoint)"""
30    def __init__(self, old, new):
31        self.old = old
32        self.new = new
33        self.diff = old.time - new.time
34        diffp = 0
35        if old.time != 0:
36            diffp = self.diff / old.time
37        self.diffp = diffp
38
39    def __repr__(self):
40        return "BenchDiff(%s, %s)" % (
41                   str(self.new),
42                   str(self.old),
43               )
44
45def main():
46    """Parses command line and writes output."""
47
48    try:
49        opts, _ = getopt.getopt(sys.argv[1:], "f:o:n:h")
50    except getopt.GetoptError, err:
51        print str(err)
52        usage()
53        sys.exit(2)
54
55    column_formats = {
56        'b' : '{bench: >28} ',
57        'c' : '{config: <4} ',
58        't' : '{time_type: <4} ',
59        'o' : '{old_time: >10.2f} ',
60        'n' : '{new_time: >10.2f} ',
61        'd' : '{diff: >+10.2f} ',
62        'p' : '{diffp: >+8.1%} ',
63    }
64    header_formats = {
65        'b' : '{bench: >28} ',
66        'c' : '{config: <4} ',
67        't' : '{time_type: <4} ',
68        'o' : '{old_time: >10} ',
69        'n' : '{new_time: >10} ',
70        'd' : '{diff: >10} ',
71        'p' : '{diffp: >8} ',
72    }
73
74    old = None
75    new = None
76    column_format = ""
77    header_format = ""
78    columns = 'bctondp'
79    header = False
80
81    for option, value in opts:
82        if option == "-o":
83            old = value
84        elif option == "-n":
85            new = value
86        elif option == "-h":
87            header = True
88        elif option == "-f":
89            columns = value
90        else:
91            usage()
92            assert False, "unhandled option"
93
94    if old is None or new is None:
95        usage()
96        sys.exit(2)
97
98    for column_char in columns:
99        if column_formats[column_char]:
100            column_format += column_formats[column_char]
101            header_format += header_formats[column_char]
102        else:
103            usage()
104            sys.exit(2)
105
106    if header:
107        print header_format.format(
108            bench='bench'
109            , config='conf'
110            , time_type='time'
111            , old_time='old'
112            , new_time='new'
113            , diff='diff'
114            , diffp='diffP'
115        )
116
117    old_benches = bench_util.parse({}, open(old, 'r'))
118    new_benches = bench_util.parse({}, open(new, 'r'))
119
120    bench_diffs = []
121    for old_bench in old_benches:
122        #filter new_benches for benches that match old_bench
123        new_bench_match = [bench for bench in new_benches
124            if old_bench.bench == bench.bench and
125               old_bench.config == bench.config and
126               old_bench.time_type == bench.time_type
127        ]
128        if (len(new_bench_match) < 1):
129            continue
130        bench_diffs.append(BenchDiff(old_bench, new_bench_match[0]))
131
132    bench_diffs.sort(key=lambda d : [d.diffp,
133                                     d.old.bench,
134                                     d.old.config,
135                                     d.old.time_type,
136                                    ])
137    for bench_diff in bench_diffs:
138        print column_format.format(
139            bench=bench_diff.old.bench.strip()
140            , config=bench_diff.old.config.strip()
141            , time_type=bench_diff.old.time_type
142            , old_time=bench_diff.old.time
143            , new_time=bench_diff.new.time
144            , diff=bench_diff.diff
145            , diffp=bench_diff.diffp
146        )
147
148if __name__ == "__main__":
149    main()
150