OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be found | |
4 # in the LICENSE file. | |
5 | |
6 """ Analyze recent SkPicture bench data, and output suggested ranges. | |
7 | |
8 The outputs can be edited and pasted to bench_expectations.txt to trigger | |
9 buildbot alerts if the actual benches are out of range. Details are documented | |
10 in the .txt file. | |
11 | |
12 Currently the easiest way to update bench_expectations.txt is to delete all skp | |
13 bench lines, run this script, and redirect outputs (">>") to be added to the | |
14 .txt file. | |
15 TODO(bensong): find a better way for updating the bench lines in place. | |
16 | |
17 Note: since input data are stored in Google Storage, you will need to set up | |
18 the corresponding library. | |
19 See http://developers.google.com/storage/docs/gspythonlibrary for details. | |
20 """ | |
21 | |
22 __author__ = 'bensong@google.com (Ben Chen)' | |
23 | |
24 import bench_util | |
25 import boto | |
26 import cStringIO | |
27 import optparse | |
28 import re | |
29 import shutil | |
30 | |
31 from oauth2_plugin import oauth2_plugin | |
32 | |
33 | |
34 # Ratios for calculating suggested picture bench upper and lower bounds. | |
35 BENCH_UB = 1.1 # Allow for 10% room for normal variance on the up side. | |
36 BENCH_LB = 0.9 | |
37 | |
38 # Further allow for a fixed amount of noise. This is especially useful for | |
39 # benches of smaller absolute value. Keeping this value small will not affect | |
40 # performance tunings. | |
41 BENCH_ALLOWED_NOISE = 10 | |
42 | |
43 # Name prefix for benchmark builders. | |
44 BENCH_BUILDER_PREFIX = 'Perf-' | |
45 | |
46 # List of platforms to track. Feel free to change it to meet your needs. | |
47 PLATFORMS = ['Perf-Mac10.8-MacMini4.1-GeForce320M-x86-Release', | |
48 'Perf-Android-Nexus7-Tegra3-Arm7-Release', | |
49 'Perf-Ubuntu12-ShuttleA-ATI5770-x86-Release', | |
50 'Perf-Win7-ShuttleA-HD2000-x86-Release', | |
51 ] | |
52 | |
53 # Filter for configs of no interest. They are old config names replaced by more | |
54 # specific ones. | |
55 CONFIGS_TO_FILTER = ['gpu', 'raster'] | |
56 | |
57 # Template for gsutil uri. | |
58 GOOGLE_STORAGE_URI_SCHEME = 'gs' | |
59 URI_BUCKET = 'chromium-skia-gm' | |
60 | |
61 # Constants for optparse. | |
62 USAGE_STRING = 'USAGE: %s [options]' | |
63 HOWTO_STRING = """ | |
64 Feel free to revise PLATFORMS for your own needs. The default is the most common | |
65 combination that we care most about. Platforms that did not run bench_pictures | |
66 in the given revision range will not have corresponding outputs. | |
67 Please check http://go/skpbench to choose a range that fits your needs. | |
68 BENCH_UB, BENCH_LB and BENCH_ALLOWED_NOISE can be changed to expand or narrow | |
69 the permitted bench ranges without triggering buidbot alerts. | |
70 """ | |
71 HELP_STRING = """ | |
72 Outputs expectation picture bench ranges for the latest revisions for the given | |
73 revision range. For instance, --rev_range=6000:6000 will return only bench | |
74 ranges for the bots that ran bench_pictures at rev 6000; --rev-range=6000:7000 | |
75 may have multiple bench data points for each bench configuration, and the code | |
76 returns bench data for the latest revision of all available (closer to 7000). | |
77 """ + HOWTO_STRING | |
78 | |
79 OPTION_REVISION_RANGE = '--rev-range' | |
80 OPTION_REVISION_RANGE_SHORT = '-r' | |
81 # Bench bench representation algorithm flag. | |
82 OPTION_REPRESENTATION_ALG = '--algorithm' | |
83 OPTION_REPRESENTATION_ALG_SHORT = '-a' | |
84 | |
85 # List of valid representation algorithms. | |
86 REPRESENTATION_ALGS = ['avg', 'min', 'med', '25th'] | |
87 | |
88 def OutputSkpBenchExpectations(rev_min, rev_max, representation_alg): | |
89 """Reads skp bench data from google storage, and outputs expectations. | |
90 | |
91 Ignores data with revisions outside [rev_min, rev_max] integer range. For | |
92 bench data with multiple revisions, we use higher revisions to calculate | |
93 expected bench values. | |
94 Uses the provided representation_alg for calculating bench representations. | |
95 """ | |
96 expectation_dic = {} | |
97 uri = boto.storage_uri(URI_BUCKET, GOOGLE_STORAGE_URI_SCHEME) | |
98 for obj in uri.get_bucket(): | |
99 # Filters out non-skp-bench files. | |
100 if ((not obj.name.startswith('perfdata/%s' % BENCH_BUILDER_PREFIX) and | |
101 not obj.name.startswith( | |
102 'playback/perfdata/%s' % BENCH_BUILDER_PREFIX)) or | |
103 obj.name.find('_data_skp_') < 0): | |
104 continue | |
105 # Ignores uninterested platforms. | |
106 platform = obj.name.split('/')[1] | |
107 if not platform.startswith(BENCH_BUILDER_PREFIX): | |
108 platform = obj.name.split('/')[2] | |
109 if not platform.startswith(BENCH_BUILDER_PREFIX): | |
110 continue # Ignores non-platform object | |
111 if platform not in PLATFORMS: | |
112 continue | |
113 # Filters by revision. | |
114 to_filter = True | |
115 for rev in range(rev_min, rev_max + 1): | |
116 if '_r%s_' % rev in obj.name: | |
117 to_filter = False | |
118 break | |
119 if to_filter: | |
120 continue | |
121 contents = cStringIO.StringIO() | |
122 obj.get_file(contents) | |
123 for point in bench_util.parse('', contents.getvalue().split('\n'), | |
124 representation_alg): | |
125 if point.config in CONFIGS_TO_FILTER: | |
126 continue | |
127 | |
128 key = '%s_%s_%s,%s-%s' % (point.bench, point.config, point.time_type, | |
129 platform, representation_alg) | |
130 # It is fine to have later revisions overwrite earlier benches, since we | |
131 # only use the latest bench within revision range to set expectations. | |
132 expectation_dic[key] = point.time | |
133 keys = expectation_dic.keys() | |
134 keys.sort() | |
135 for key in keys: | |
136 bench_val = expectation_dic[key] | |
137 # Prints out expectation lines. | |
138 print '%s,%.3f,%.3f,%.3f' % (key, bench_val, | |
139 bench_val * BENCH_LB - BENCH_ALLOWED_NOISE, | |
140 bench_val * BENCH_UB + BENCH_ALLOWED_NOISE) | |
141 | |
142 def main(): | |
143 """Parses flags and outputs expected Skia picture bench results.""" | |
144 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING) | |
145 parser.add_option(OPTION_REVISION_RANGE_SHORT, OPTION_REVISION_RANGE, | |
146 dest='rev_range', | |
147 help='(Mandatory) revision range separated by ":", e.g., 6000:6005') | |
148 parser.add_option(OPTION_REPRESENTATION_ALG_SHORT, OPTION_REPRESENTATION_ALG, | |
149 dest='alg', default='25th', | |
150 help=('Bench representation algorithm. One of ' | |
151 '%s. Default to "25th".' % str(REPRESENTATION_ALGS))) | |
152 (options, args) = parser.parse_args() | |
153 if options.rev_range: | |
154 range_match = re.search('(\d+)\:(\d+)', options.rev_range) | |
155 if not range_match: | |
156 parser.error('Wrong format for rev-range [%s]' % options.rev_range) | |
157 else: | |
158 rev_min = int(range_match.group(1)) | |
159 rev_max = int(range_match.group(2)) | |
160 OutputSkpBenchExpectations(rev_min, rev_max, options.alg) | |
161 else: | |
162 parser.error('Please provide mandatory flag %s' % OPTION_REVISION_RANGE) | |
163 | |
164 | |
165 if '__main__' == __name__: | |
166 main() | |
OLD | NEW |