bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 2 | ''' |
| 3 | Created on May 16, 2011 |
| 4 | |
| 5 | @author: bungeman |
| 6 | ''' |
| 7 | import sys |
| 8 | import getopt |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 9 | import bench_util |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 10 | |
| 11 | def usage(): |
| 12 | """Prints simple usage information.""" |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 13 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 14 | print '-o <file> the old bench output file.' |
| 15 | print '-n <file> the new bench output file.' |
| 16 | print '-h causes headers to be output.' |
djsollen@google.com | f3d3d96 | 2012-08-21 19:10:05 +0000 | [diff] [blame] | 17 | print '-s <stat> the type of statistical analysis used' |
| 18 | print ' Not specifying is the same as -s "avg".' |
| 19 | print ' avg: average of all data points' |
| 20 | print ' min: minimum of all data points' |
| 21 | print ' med: median of all data points' |
| 22 | print ' 25th: twenty-fifth percentile for all data points' |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 23 | print '-f <fieldSpec> which fields to output and in what order.' |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 24 | print ' Not specifying is the same as -f "bctondp".' |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 25 | print ' b: bench' |
| 26 | print ' c: config' |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 27 | print ' t: time type' |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 28 | print ' o: old time' |
| 29 | print ' n: new time' |
| 30 | print ' d: diff' |
| 31 | print ' p: percent diff' |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 32 | print '-t use tab delimited format for output.' |
| 33 | print '--match <bench> only matches benches which begin with <bench>.' |
| 34 | |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 35 | class BenchDiff: |
| 36 | """A compare between data points produced by bench. |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 37 | |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 38 | (BenchDataPoint, BenchDataPoint)""" |
| 39 | def __init__(self, old, new): |
| 40 | self.old = old |
| 41 | self.new = new |
| 42 | self.diff = old.time - new.time |
| 43 | diffp = 0 |
| 44 | if old.time != 0: |
| 45 | diffp = self.diff / old.time |
| 46 | self.diffp = diffp |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 47 | |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 48 | def __repr__(self): |
| 49 | return "BenchDiff(%s, %s)" % ( |
| 50 | str(self.new), |
| 51 | str(self.old), |
| 52 | ) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 53 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 54 | def main(): |
| 55 | """Parses command line and writes output.""" |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 56 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 57 | try: |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 58 | opts, _ = getopt.getopt(sys.argv[1:], "f:o:n:s:ht", ['match=']) |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 59 | except getopt.GetoptError, err: |
| 60 | print str(err) |
| 61 | usage() |
| 62 | sys.exit(2) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 63 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 64 | old = None |
| 65 | new = None |
| 66 | column_format = "" |
| 67 | header_format = "" |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 68 | columns = 'bctondp' |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 69 | header = False |
djsollen@google.com | f3d3d96 | 2012-08-21 19:10:05 +0000 | [diff] [blame] | 70 | stat_type = "avg" |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 71 | use_tabs = False |
| 72 | match_bench = None; |
| 73 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 74 | for option, value in opts: |
| 75 | if option == "-o": |
| 76 | old = value |
| 77 | elif option == "-n": |
| 78 | new = value |
| 79 | elif option == "-h": |
| 80 | header = True |
| 81 | elif option == "-f": |
| 82 | columns = value |
djsollen@google.com | f3d3d96 | 2012-08-21 19:10:05 +0000 | [diff] [blame] | 83 | elif option == "-s": |
| 84 | stat_type = value |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 85 | elif option == "-t": |
| 86 | use_tabs = True |
| 87 | elif option == "--match": |
| 88 | match_bench = value |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 89 | else: |
| 90 | usage() |
| 91 | assert False, "unhandled option" |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 92 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 93 | if old is None or new is None: |
| 94 | usage() |
| 95 | sys.exit(2) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 96 | |
| 97 | old_benches = bench_util.parse({}, open(old, 'r'), stat_type) |
| 98 | new_benches = bench_util.parse({}, open(new, 'r'), stat_type) |
| 99 | |
| 100 | bench_diffs = [] |
| 101 | for old_bench in old_benches: |
| 102 | #filter benches by the match criteria |
| 103 | if match_bench and not old_bench.bench.startswith(match_bench): |
| 104 | continue |
| 105 | |
| 106 | #filter new_benches for benches that match old_bench |
| 107 | new_bench_match = [bench for bench in new_benches |
| 108 | if old_bench.bench == bench.bench and |
| 109 | old_bench.config == bench.config and |
| 110 | old_bench.time_type == bench.time_type |
| 111 | ] |
| 112 | if (len(new_bench_match) < 1): |
| 113 | continue |
| 114 | bench_diffs.append(BenchDiff(old_bench, new_bench_match[0])) |
| 115 | |
| 116 | if use_tabs: |
| 117 | column_formats = { |
| 118 | 'b' : '{bench}\t', |
| 119 | 'c' : '{config}\t', |
| 120 | 't' : '{time_type}\t', |
| 121 | 'o' : '{old_time: 0.2f}\t', |
| 122 | 'n' : '{new_time: 0.2f}\t', |
| 123 | 'd' : '{diff: 0.2f}\t', |
| 124 | 'p' : '{diffp: 0.1%}\t', |
| 125 | } |
| 126 | header_formats = { |
| 127 | 'b' : '{bench}\t', |
| 128 | 'c' : '{config}\t', |
| 129 | 't' : '{time_type}\t', |
| 130 | 'o' : '{old_time}\t', |
| 131 | 'n' : '{new_time}\t', |
| 132 | 'd' : '{diff}\t', |
| 133 | 'p' : '{diffp}\t', |
| 134 | } |
| 135 | else: |
| 136 | bench_max_len = max(map(lambda b: len(b.old.bench), bench_diffs)) |
| 137 | config_max_len = max(map(lambda b: len(b.old.config), bench_diffs)) |
| 138 | column_formats = { |
| 139 | 'b' : '{bench: >%d} ' % (bench_max_len), |
| 140 | 'c' : '{config: <%d} ' % (config_max_len), |
| 141 | 't' : '{time_type: <4} ', |
| 142 | 'o' : '{old_time: >10.2f} ', |
| 143 | 'n' : '{new_time: >10.2f} ', |
| 144 | 'd' : '{diff: >+10.2f} ', |
| 145 | 'p' : '{diffp: >+8.1%} ', |
| 146 | } |
| 147 | header_formats = { |
| 148 | 'b' : '{bench: >%d} ' % (bench_max_len), |
| 149 | 'c' : '{config: <%d} ' % (config_max_len), |
| 150 | 't' : '{time_type: <4} ', |
| 151 | 'o' : '{old_time: >10} ', |
| 152 | 'n' : '{new_time: >10} ', |
| 153 | 'd' : '{diff: >10} ', |
| 154 | 'p' : '{diffp: >8} ', |
| 155 | } |
| 156 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 157 | for column_char in columns: |
| 158 | if column_formats[column_char]: |
| 159 | column_format += column_formats[column_char] |
| 160 | header_format += header_formats[column_char] |
| 161 | else: |
| 162 | usage() |
| 163 | sys.exit(2) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 164 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 165 | if header: |
| 166 | print header_format.format( |
| 167 | bench='bench' |
| 168 | , config='conf' |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 169 | , time_type='time' |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 170 | , old_time='old' |
| 171 | , new_time='new' |
| 172 | , diff='diff' |
| 173 | , diffp='diffP' |
| 174 | ) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 175 | |
bungeman@google.com | 85669f9 | 2011-06-17 13:58:14 +0000 | [diff] [blame] | 176 | bench_diffs.sort(key=lambda d : [d.diffp, |
| 177 | d.old.bench, |
| 178 | d.old.config, |
| 179 | d.old.time_type, |
| 180 | ]) |
| 181 | for bench_diff in bench_diffs: |
| 182 | print column_format.format( |
| 183 | bench=bench_diff.old.bench.strip() |
| 184 | , config=bench_diff.old.config.strip() |
| 185 | , time_type=bench_diff.old.time_type |
| 186 | , old_time=bench_diff.old.time |
| 187 | , new_time=bench_diff.new.time |
| 188 | , diff=bench_diff.diff |
| 189 | , diffp=bench_diff.diffp |
| 190 | ) |
bungeman@google.com | 7047665 | 2013-01-30 19:22:51 +0000 | [diff] [blame] | 191 | |
bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 192 | if __name__ == "__main__": |
| 193 | main() |