1 #!/usr/bin/env python 2 3 # Copyright 2016 Google Inc. 4 # 5 # Use of this source code is governed by a BSD-style license that can be 6 # found in the LICENSE file. 7 8 from __future__ import print_function 9 from _benchresult import BenchResult 10 from argparse import ArgumentParser 11 from collections import defaultdict 12 import json 13 import sys 14 15 __argparse = ArgumentParser(description=""" 16 17 Formats skpbench.py outputs for Skia Perf. 18 19 """) 20 21 __argparse.add_argument('sources', 22 nargs='+', help="source files that contain skpbench results") 23 __argparse.add_argument('--properties', 24 nargs='*', help="space-separated key/value pairs identifying the run") 25 __argparse.add_argument('--key', 26 nargs='*', help="space-separated key/value pairs identifying the builder") 27 __argparse.add_argument('-o', '--outfile', 28 default='-', help="output file ('-' for stdout)") 29 30 FLAGS = __argparse.parse_args() 31 32 33 class JSONDict(dict): 34 """Simple class for building a JSON dictionary 35 36 Returns another JSONDict upon accessing an undefined item. Does not allow an 37 item to change once it has been inserted. 38 39 """ 40 def __init__(self, key_value_pairs=None): 41 dict.__init__(self) 42 if not key_value_pairs: 43 return 44 if len(key_value_pairs) % 2: 45 raise Exception("uneven number of key/value arguments.") 46 for k,v in zip(key_value_pairs[::2], key_value_pairs[1::2]): 47 self[k] = v 48 49 def __getitem__(self, key): 50 if not key in self: 51 dict.__setitem__(self, key, JSONDict()) 52 return dict.__getitem__(self, key) 53 54 def __setitem__(self, key, val): 55 if key in self: 56 raise Exception("%s: tried to set already-defined JSONDict item\n" 57 " old value: '%s'\n" 58 " new value: '%s'" % (key, self[key], val)) 59 dict.__setitem__(self, key, val) 60 61 def emit(self, outfile): 62 json.dump(self, outfile, indent=4, separators=(',', ' : '), sort_keys=True) 63 print('', file=outfile) 64 65 def main(): 66 data = JSONDict( 67 FLAGS.properties + \ 68 ['key', JSONDict(FLAGS.key + \ 69 ['bench_type', 'playback', \ 70 'source_type', 'skp'])]) 71 72 for src in FLAGS.sources: 73 with open(src, mode='r') as infile: 74 for line in infile: 75 match = BenchResult.match(line) 76 if not match: 77 continue 78 if match.sample_ms != 50: 79 raise Exception("%s: unexpected sample_ms != 50" % match.sample_ms) 80 for result in ('accum', 'median'): 81 data['results'][match.bench][match.config] \ 82 ['%s_%s_%s' % (result, match.clock, match.metric)] = \ 83 getattr(match, result) 84 85 if FLAGS.outfile != '-': 86 with open(FLAGS.outfile, 'w+') as outfile: 87 data.emit(outfile) 88 else: 89 data.emit(sys.stdout) 90 91 if __name__ == '__main__': 92 main() 93