|  | #!/usr/bin/env python | 
|  | ''' | 
|  | Created on May 16, 2011 | 
|  |  | 
|  | @author: bungeman | 
|  | ''' | 
|  | import sys | 
|  | import getopt | 
|  | import bench_util | 
|  |  | 
|  | def usage(): | 
|  | """Prints simple usage information.""" | 
|  |  | 
|  | print '-o <file> the old bench output file.' | 
|  | print '-n <file> the new bench output file.' | 
|  | print '-h causes headers to be output.' | 
|  | print '-s <stat> the type of statistical analysis used' | 
|  | print '   Not specifying is the same as -s "avg".' | 
|  | print '  avg: average of all data points' | 
|  | print '  min: minimum of all data points' | 
|  | print '  med: median of all data points' | 
|  | print '  25th: twenty-fifth percentile for all data points' | 
|  | print '-f <fieldSpec> which fields to output and in what order.' | 
|  | print '   Not specifying is the same as -f "bctondp".' | 
|  | print '  b: bench' | 
|  | print '  c: config' | 
|  | print '  t: time type' | 
|  | print '  o: old time' | 
|  | print '  n: new time' | 
|  | print '  d: diff' | 
|  | print '  p: percent diff' | 
|  | print '-t use tab delimited format for output.' | 
|  | print '--match <bench> only matches benches which begin with <bench>.' | 
|  |  | 
|  | class BenchDiff: | 
|  | """A compare between data points produced by bench. | 
|  |  | 
|  | (BenchDataPoint, BenchDataPoint)""" | 
|  | def __init__(self, old, new): | 
|  | self.old = old | 
|  | self.new = new | 
|  | self.diff = old.time - new.time | 
|  | diffp = 0 | 
|  | if old.time != 0: | 
|  | diffp = self.diff / old.time | 
|  | self.diffp = diffp | 
|  |  | 
|  | def __repr__(self): | 
|  | return "BenchDiff(%s, %s)" % ( | 
|  | str(self.new), | 
|  | str(self.old), | 
|  | ) | 
|  |  | 
|  | def main(): | 
|  | """Parses command line and writes output.""" | 
|  |  | 
|  | try: | 
|  | opts, _ = getopt.getopt(sys.argv[1:], "f:o:n:s:ht", ['match=']) | 
|  | except getopt.GetoptError, err: | 
|  | print str(err) | 
|  | usage() | 
|  | sys.exit(2) | 
|  |  | 
|  | old = None | 
|  | new = None | 
|  | column_format = "" | 
|  | header_format = "" | 
|  | columns = 'bctondp' | 
|  | header = False | 
|  | stat_type = "avg" | 
|  | use_tabs = False | 
|  | match_bench = None; | 
|  |  | 
|  | for option, value in opts: | 
|  | if option == "-o": | 
|  | old = value | 
|  | elif option == "-n": | 
|  | new = value | 
|  | elif option == "-h": | 
|  | header = True | 
|  | elif option == "-f": | 
|  | columns = value | 
|  | elif option == "-s": | 
|  | stat_type = value | 
|  | elif option == "-t": | 
|  | use_tabs = True | 
|  | elif option == "--match": | 
|  | match_bench = value | 
|  | else: | 
|  | usage() | 
|  | assert False, "unhandled option" | 
|  |  | 
|  | if old is None or new is None: | 
|  | usage() | 
|  | sys.exit(2) | 
|  |  | 
|  | old_benches = bench_util.parse({}, open(old, 'r'), stat_type) | 
|  | new_benches = bench_util.parse({}, open(new, 'r'), stat_type) | 
|  |  | 
|  | bench_diffs = [] | 
|  | for old_bench in old_benches: | 
|  | #filter benches by the match criteria | 
|  | if match_bench and not old_bench.bench.startswith(match_bench): | 
|  | continue | 
|  |  | 
|  | #filter new_benches for benches that match old_bench | 
|  | new_bench_match = [bench for bench in new_benches | 
|  | if old_bench.bench == bench.bench and | 
|  | old_bench.config == bench.config and | 
|  | old_bench.time_type == bench.time_type | 
|  | ] | 
|  | if (len(new_bench_match) < 1): | 
|  | continue | 
|  | bench_diffs.append(BenchDiff(old_bench, new_bench_match[0])) | 
|  |  | 
|  | if use_tabs: | 
|  | column_formats = { | 
|  | 'b' : '{bench}\t', | 
|  | 'c' : '{config}\t', | 
|  | 't' : '{time_type}\t', | 
|  | 'o' : '{old_time: 0.2f}\t', | 
|  | 'n' : '{new_time: 0.2f}\t', | 
|  | 'd' : '{diff: 0.2f}\t', | 
|  | 'p' : '{diffp: 0.1%}\t', | 
|  | } | 
|  | header_formats = { | 
|  | 'b' : '{bench}\t', | 
|  | 'c' : '{config}\t', | 
|  | 't' : '{time_type}\t', | 
|  | 'o' : '{old_time}\t', | 
|  | 'n' : '{new_time}\t', | 
|  | 'd' : '{diff}\t', | 
|  | 'p' : '{diffp}\t', | 
|  | } | 
|  | else: | 
|  | bench_max_len = max(map(lambda b: len(b.old.bench), bench_diffs)) | 
|  | config_max_len = max(map(lambda b: len(b.old.config), bench_diffs)) | 
|  | column_formats = { | 
|  | 'b' : '{bench: >%d} ' % (bench_max_len), | 
|  | 'c' : '{config: <%d} ' % (config_max_len), | 
|  | 't' : '{time_type: <4} ', | 
|  | 'o' : '{old_time: >10.2f} ', | 
|  | 'n' : '{new_time: >10.2f} ', | 
|  | 'd' : '{diff: >+10.2f} ', | 
|  | 'p' : '{diffp: >+8.1%} ', | 
|  | } | 
|  | header_formats = { | 
|  | 'b' : '{bench: >%d} ' % (bench_max_len), | 
|  | 'c' : '{config: <%d} ' % (config_max_len), | 
|  | 't' : '{time_type: <4} ', | 
|  | 'o' : '{old_time: >10} ', | 
|  | 'n' : '{new_time: >10} ', | 
|  | 'd' : '{diff: >10} ', | 
|  | 'p' : '{diffp: >8} ', | 
|  | } | 
|  |  | 
|  | for column_char in columns: | 
|  | if column_formats[column_char]: | 
|  | column_format += column_formats[column_char] | 
|  | header_format += header_formats[column_char] | 
|  | else: | 
|  | usage() | 
|  | sys.exit(2) | 
|  |  | 
|  | if header: | 
|  | print header_format.format( | 
|  | bench='bench' | 
|  | , config='conf' | 
|  | , time_type='time' | 
|  | , old_time='old' | 
|  | , new_time='new' | 
|  | , diff='diff' | 
|  | , diffp='diffP' | 
|  | ) | 
|  |  | 
|  | bench_diffs.sort(key=lambda d : [d.diffp, | 
|  | d.old.bench, | 
|  | d.old.config, | 
|  | d.old.time_type, | 
|  | ]) | 
|  | for bench_diff in bench_diffs: | 
|  | print column_format.format( | 
|  | bench=bench_diff.old.bench.strip() | 
|  | , config=bench_diff.old.config.strip() | 
|  | , time_type=bench_diff.old.time_type | 
|  | , old_time=bench_diff.old.time | 
|  | , new_time=bench_diff.new.time | 
|  | , diff=bench_diff.diff | 
|  | , diffp=bench_diff.diffp | 
|  | ) | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |