| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 ''' | |
| 3 Created on May 16, 2011 | |
| 4 | |
| 5 @author: bungeman | |
| 6 ''' | |
| 7 import sys | |
| 8 import getopt | |
| 9 import bench_util | |
| 10 | |
| 11 def usage(): | |
| 12 """Prints simple usage information.""" | |
| 13 | |
| 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.' | |
| 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' | |
| 23 print '-f <fieldSpec> which fields to output and in what order.' | |
| 24 print ' Not specifying is the same as -f "bctondp".' | |
| 25 print ' b: bench' | |
| 26 print ' c: config' | |
| 27 print ' t: time type' | |
| 28 print ' o: old time' | |
| 29 print ' n: new time' | |
| 30 print ' d: diff' | |
| 31 print ' p: percent diff' | |
| 32 print '-t use tab delimited format for output.' | |
| 33 print '--match <bench> only matches benches which begin with <bench>.' | |
| 34 | |
| 35 class BenchDiff: | |
| 36 """A compare between data points produced by bench. | |
| 37 | |
| 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 | |
| 47 | |
| 48 def __repr__(self): | |
| 49 return "BenchDiff(%s, %s)" % ( | |
| 50 str(self.new), | |
| 51 str(self.old), | |
| 52 ) | |
| 53 | |
| 54 def main(): | |
| 55 """Parses command line and writes output.""" | |
| 56 | |
| 57 try: | |
| 58 opts, _ = getopt.getopt(sys.argv[1:], "f:o:n:s:ht", ['match=']) | |
| 59 except getopt.GetoptError, err: | |
| 60 print str(err) | |
| 61 usage() | |
| 62 sys.exit(2) | |
| 63 | |
| 64 old = None | |
| 65 new = None | |
| 66 column_format = "" | |
| 67 header_format = "" | |
| 68 columns = 'bctondp' | |
| 69 header = False | |
| 70 stat_type = "avg" | |
| 71 use_tabs = False | |
| 72 match_bench = None; | |
| 73 | |
| 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 | |
| 83 elif option == "-s": | |
| 84 stat_type = value | |
| 85 elif option == "-t": | |
| 86 use_tabs = True | |
| 87 elif option == "--match": | |
| 88 match_bench = value | |
| 89 else: | |
| 90 usage() | |
| 91 assert False, "unhandled option" | |
| 92 | |
| 93 if old is None or new is None: | |
| 94 usage() | |
| 95 sys.exit(2) | |
| 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 | |
| 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) | |
| 164 | |
| 165 if header: | |
| 166 print header_format.format( | |
| 167 bench='bench' | |
| 168 , config='conf' | |
| 169 , time_type='time' | |
| 170 , old_time='old' | |
| 171 , new_time='new' | |
| 172 , diff='diff' | |
| 173 , diffp='diffP' | |
| 174 ) | |
| 175 | |
| 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 ) | |
| 191 | |
| 192 if __name__ == "__main__": | |
| 193 main() | |
| OLD | NEW |