Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 #!/usr/bin/env python2.4
2 """usage: %progname candidate_path baseline_path
3 """
5 import json
6 import optparse
7 from contextlib import nested
8 from operator import itemgetter
11 def avg(seq):
12 return sum(seq) / len(seq)
15 def compare(current, baseline):
16 percent_speedups = []
17 for key, current_result in current.iteritems():
18 try:
19 baseline_result = baseline[key]
20 except KeyError:
21 print key, 'missing from baseline'
22 continue
23 val_getter = itemgetter('average_ms', 'stddev_ms')
24 base_avg, base_stddev = val_getter(baseline_result)
25 current_avg, current_stddev = val_getter(current_result)
26 t_best, t_worst = current_avg - current_stddev, current_avg + current_stddev
27 base_t_best, base_t_worst = base_avg - base_stddev, base_avg + base_stddev
28 fmt = '%30s: %s'
29 if t_worst < base_t_best: # Worst takes less time (better) than baseline's best.
30 speedup = -((t_worst - base_t_best) / base_t_best) * 100
31 result = 'faster: %6.2fms < baseline %6.2fms (%+6.2f%%)' % \
32 (t_worst, base_t_best, speedup)
33 percent_speedups.append(speedup)
34 elif t_best > base_t_worst: # Best takes more time (worse) than baseline's worst.
35 slowdown = -((t_best - base_t_worst) / base_t_worst) * 100
36 result = 'SLOWER: %6.2fms > baseline %6.2fms (%+6.2f%%) ' % \
37 (t_best, base_t_worst, slowdown)
38 percent_speedups.append(slowdown)
39 else:
40 result = 'Meh.'
41 print '%30s: %s' % (key, result)
42 if percent_speedups:
43 print 'Average speedup: %.2f%%' % avg(percent_speedups)
46 def compare_immediate(current_map, baseline_path):
47 baseline_file = open(baseline_path)
48 baseline_map = json.load(baseline_file)
49 baseline_file.close()
50 compare(current_map, baseline_map)
53 def main(candidate_path, baseline_path):
54 candidate_file, baseline_file = open(candidate_path), open(baseline_path)
55 candidate = json.load(candidate_file)
56 baseline = json.load(baseline_file)
57 compare(candidate, baseline)
58 candidate_file.close()
59 baseline_file.close()
62 if __name__ == '__main__':
63 parser = optparse.OptionParser(usage=__doc__.strip())
64 options, args = parser.parse_args()
65 try:
66 candidate_path = args.pop(0)
67 except IndexError:
68 parser.error('A JSON filepath to compare against baseline is required')
69 try:
70 baseline_path = args.pop(0)
71 except IndexError:
72 parser.error('A JSON filepath for baseline is required')
73 main(candidate_path, baseline_path)