| 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 |