bungeman@google.com | d1a416a | 2011-05-18 18:37:07 +0000 | [diff] [blame] | 1 | ''' |
| 2 | Created on May 16, 2011 |
| 3 | |
| 4 | @author: bungeman |
| 5 | ''' |
| 6 | import sys |
| 7 | import getopt |
| 8 | import re |
| 9 | |
| 10 | def parse(lines): |
| 11 | """Takes iterable lines of bench output, returns {bench:{config:time}}.""" |
| 12 | |
| 13 | benches = {} |
| 14 | current_bench = None |
| 15 | |
| 16 | for line in lines: |
| 17 | #see if this line starts a new bench |
| 18 | new_bench = re.search('running bench \[\d+ \d+\] (.{28})', line) |
| 19 | if new_bench: |
| 20 | current_bench = new_bench.group(1) |
| 21 | |
| 22 | #add configs on this line to the current bench |
| 23 | if current_bench: |
| 24 | for new_config in re.finditer(' (.{4}): msecs = (\d+\.\d+)', line): |
| 25 | current_config = new_config.group(1) |
| 26 | current_time = float(new_config.group(2)) |
| 27 | if current_bench in benches: |
| 28 | benches[current_bench][current_config] = current_time |
| 29 | else: |
| 30 | benches[current_bench] = {current_config : current_time} |
| 31 | |
| 32 | return benches |
| 33 | |
| 34 | def usage(): |
| 35 | """Prints simple usage information.""" |
| 36 | |
| 37 | print '-o <file> the old bench output file.' |
| 38 | print '-n <file> the new bench output file.' |
| 39 | print '-h causes headers to be output.' |
| 40 | print '-f <fieldSpec> which fields to output and in what order.' |
| 41 | print ' Not specifying is the same as -f "bcondp".' |
| 42 | print ' b: bench' |
| 43 | print ' c: config' |
| 44 | print ' o: old time' |
| 45 | print ' n: new time' |
| 46 | print ' d: diff' |
| 47 | print ' p: percent diff' |
| 48 | |
| 49 | |
| 50 | def main(): |
| 51 | """Parses command line and writes output.""" |
| 52 | |
| 53 | try: |
| 54 | opts, args = getopt.getopt(sys.argv[1:], "f:o:n:h") |
| 55 | except getopt.GetoptError, err: |
| 56 | print str(err) |
| 57 | usage() |
| 58 | sys.exit(2) |
| 59 | |
| 60 | column_formats = { |
| 61 | 'b' : '{bench: >28} ', |
| 62 | 'c' : '{config: <4} ', |
| 63 | 'o' : '{old_time: >10.2f} ', |
| 64 | 'n' : '{new_time: >10.2f} ', |
| 65 | 'd' : '{diff: >+10.2f} ', |
| 66 | 'p' : '{diffp: >+7.1%} ', |
| 67 | } |
| 68 | header_formats = { |
| 69 | 'b' : '{bench: >28} ', |
| 70 | 'c' : '{config: <4} ', |
| 71 | 'o' : '{old_time: >10} ', |
| 72 | 'n' : '{new_time: >10} ', |
| 73 | 'd' : '{diff: >10} ', |
| 74 | 'p' : '{diffp: >7} ', |
| 75 | } |
| 76 | |
| 77 | old = None |
| 78 | new = None |
| 79 | column_format = "" |
| 80 | header_format = "" |
| 81 | columns = 'bcondp' |
| 82 | header = False |
| 83 | |
| 84 | for option, value in opts: |
| 85 | if option == "-o": |
| 86 | old = value |
| 87 | elif option == "-n": |
| 88 | new = value |
| 89 | elif option == "-h": |
| 90 | header = True |
| 91 | elif option == "-f": |
| 92 | columns = value |
| 93 | else: |
| 94 | usage() |
| 95 | assert False, "unhandled option" |
| 96 | |
| 97 | if old is None or new is None: |
| 98 | usage() |
| 99 | sys.exit(2) |
| 100 | |
| 101 | for column_char in columns: |
| 102 | if column_formats[column_char]: |
| 103 | column_format += column_formats[column_char] |
| 104 | header_format += header_formats[column_char] |
| 105 | else: |
| 106 | usage() |
| 107 | sys.exit(2) |
| 108 | |
| 109 | if header: |
| 110 | print header_format.format( |
| 111 | bench='bench' |
| 112 | , config='conf' |
| 113 | , old_time='old' |
| 114 | , new_time='new' |
| 115 | , diff='diff' |
| 116 | , diffp='diffP' |
| 117 | ) |
| 118 | |
| 119 | old_benches = parse(open(old, 'r')) |
| 120 | new_benches = parse(open(new, 'r')) |
| 121 | |
| 122 | for old_bench, old_configs in old_benches.items(): |
| 123 | if old_bench in new_benches: |
| 124 | new_configs = new_benches[old_bench] |
| 125 | for old_config, old_time in old_configs.items(): |
| 126 | if old_config in new_configs: |
| 127 | new_time = new_configs[old_config] |
| 128 | old_time = old_configs[old_config] |
| 129 | print column_format.format( |
| 130 | bench=old_bench.strip() |
| 131 | , config=old_config.strip() |
| 132 | , old_time=old_time |
| 133 | , new_time=new_time |
| 134 | , diff=(old_time - new_time) |
| 135 | , diffp=((old_time-new_time)/old_time) |
| 136 | ) |
| 137 | |
| 138 | |
| 139 | if __name__ == "__main__": |
| 140 | main() |