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 or Microbench data, and output suggested ranges. | |
7 | |
8 The outputs can be edited and pasted to bench_expectations_<builder>.txt to | |
9 trigger buildbot alerts if the actual benches are out of range. Details are | |
10 documented in the corresponding .txt file for each builder. | |
11 | |
12 Currently the easiest way to batch update bench_expectations_<builder>.txt is to | |
13 delete all bench lines, run this script, and redirect outputs (">>") to be added | |
14 to the corresponding .txt file for each perf builder. | |
15 You can also just manually change a few lines of interest, of course. | |
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 or benchmain 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 benches 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 representation algorithm flag. | |
82 OPTION_REPRESENTATION_ALG = '--algorithm' | |
83 OPTION_REPRESENTATION_ALG_SHORT = '-a' | |
84 # Bench type to examine. Either 'micro' or 'skp'. | |
85 OPTION_BENCH_TYPE = '--bench-type' | |
86 OPTION_BENCH_TYPE_SHORT = '-b' | |
87 | |
88 # List of valid bench types. | |
89 BENCH_TYPES = ['micro', 'skp'] | |
90 # List of valid representation algorithms. | |
91 REPRESENTATION_ALGS = ['avg', 'min', 'med', '25th'] | |
92 | |
93 def OutputBenchExpectations(bench_type, rev_min, rev_max, representation_alg): | |
94 """Reads bench data from google storage, and outputs expectations. | |
95 | |
96 Ignores data with revisions outside [rev_min, rev_max] integer range. For | |
97 bench data with multiple revisions, we use higher revisions to calculate | |
98 expected bench values. | |
99 bench_type is either 'micro' or 'skp', according to the flag '-b'. | |
100 Uses the provided representation_alg for calculating bench representations. | |
101 """ | |
102 if bench_type not in BENCH_TYPES: | |
103 raise Exception('Not valid bench_type! (%s)' % BENCH_TYPES) | |
104 expectation_dic = {} | |
105 uri = boto.storage_uri(URI_BUCKET, GOOGLE_STORAGE_URI_SCHEME) | |
106 for obj in uri.get_bucket(): | |
107 # Filters out non-bench files. | |
108 if ((not obj.name.startswith('perfdata/%s' % BENCH_BUILDER_PREFIX) and | |
109 not obj.name.startswith( | |
110 'playback/perfdata/%s' % BENCH_BUILDER_PREFIX)) or | |
111 obj.name.find('_data') < 0): | |
112 continue | |
113 if ((bench_type == 'micro' and obj.name.find('_data_skp_') > 0) or | |
114 (bench_type == 'skp' and obj.name.find('_skp_') < 0)): | |
115 # Skips wrong bench type. | |
116 continue | |
117 # Ignores uninterested platforms. | |
118 platform = obj.name.split('/')[1] | |
119 if not platform.startswith(BENCH_BUILDER_PREFIX): | |
120 platform = obj.name.split('/')[2] | |
121 if not platform.startswith(BENCH_BUILDER_PREFIX): | |
122 continue # Ignores non-platform object | |
123 if platform not in PLATFORMS: | |
124 continue | |
125 # Filters by revision. | |
126 to_filter = True | |
127 for rev in range(rev_min, rev_max + 1): | |
128 if '_r%s_' % rev in obj.name: | |
129 to_filter = False | |
130 break | |
131 if to_filter: | |
132 continue | |
133 contents = cStringIO.StringIO() | |
134 obj.get_file(contents) | |
135 for point in bench_util.parse('', contents.getvalue().split('\n'), | |
136 representation_alg): | |
137 if point.config in CONFIGS_TO_FILTER: | |
138 continue | |
139 | |
140 key = '%s_%s_%s,%s-%s' % (point.bench, point.config, point.time_type, | |
141 platform, representation_alg) | |
142 # It is fine to have later revisions overwrite earlier benches, since we | |
143 # only use the latest bench within revision range to set expectations. | |
144 expectation_dic[key] = point.time | |
145 keys = expectation_dic.keys() | |
146 keys.sort() | |
147 for key in keys: | |
148 bench_val = expectation_dic[key] | |
149 # Prints out expectation lines. | |
150 print '%s,%.3f,%.3f,%.3f' % (key, bench_val, | |
151 bench_val * BENCH_LB - BENCH_ALLOWED_NOISE, | |
152 bench_val * BENCH_UB + BENCH_ALLOWED_NOISE) | |
153 | |
154 def main(): | |
155 """Parses flags and outputs expected Skia bench results.""" | |
156 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING) | |
157 parser.add_option(OPTION_REVISION_RANGE_SHORT, OPTION_REVISION_RANGE, | |
158 dest='rev_range', | |
159 help='(Mandatory) revision range separated by ":", e.g., 6000:6005') | |
160 parser.add_option(OPTION_BENCH_TYPE_SHORT, OPTION_BENCH_TYPE, | |
161 dest='bench_type', default='skp', | |
162 help=('Bench type, either "skp" or "micro". Default to "skp".')) | |
163 parser.add_option(OPTION_REPRESENTATION_ALG_SHORT, OPTION_REPRESENTATION_ALG, | |
164 dest='alg', default='25th', | |
165 help=('Bench representation algorithm. One of ' | |
166 '%s. Default to "25th".' % str(REPRESENTATION_ALGS))) | |
167 (options, args) = parser.parse_args() | |
168 if options.rev_range: | |
169 range_match = re.search('(\d+)\:(\d+)', options.rev_range) | |
170 if not range_match: | |
171 parser.error('Wrong format for rev-range [%s]' % options.rev_range) | |
172 else: | |
173 rev_min = int(range_match.group(1)) | |
174 rev_max = int(range_match.group(2)) | |
175 OutputBenchExpectations(options.bench_type, rev_min, rev_max, options.alg) | |
176 else: | |
177 parser.error('Please provide mandatory flag %s' % OPTION_REVISION_RANGE) | |
178 | |
179 | |
180 if '__main__' == __name__: | |
181 main() | |
OLD | NEW |