Home | History | Annotate | Download | only in bench
      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()
    141