blob: e6c4295f9175e50c2805d59fd9c895a74591eead [file] [log] [blame]
bensong@google.comfa1d4ea2012-11-27 17:30:26 +00001#!/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
8The outputs can be edited and pasted to bench_expectations.txt to trigger
9buildbot alerts if the actual benches are out of range. Details are documented
10in the .txt file.
11
12Currently the easiest way to update bench_expectations.txt is to delete all skp
13bench lines, run this script, and redirect outputs (">>") to be added to the
14.txt file.
15TODO(bensong): find a better way for updating the bench lines in place.
16
17Note: since input data are stored in Google Storage, you will need to set up
18the corresponding library.
19See http://developers.google.com/storage/docs/gspythonlibrary for details.
20"""
21
22__author__ = 'bensong@google.com (Ben Chen)'
23
24import bench_util
25import boto
26import cStringIO
27import optparse
28import re
29import shutil
30
31from oauth2_plugin import oauth2_plugin
32
33
34# Ratios for calculating suggested picture bench upper and lower bounds.
bensong@google.comdc2dd2e2012-11-27 21:52:32 +000035BENCH_UB = 1.1 # Allow for 10% room for normal variance on the up side.
36BENCH_LB = 0.85
bensong@google.comfa1d4ea2012-11-27 17:30:26 +000037
38# List of platforms to track.
39PLATFORMS = ['Mac_Float_Bench_32',
40 'Nexus10_4-1_Float_Bench_32',
41 'Shuttle_Ubuntu12_ATI5770_Float_Bench_32',
42 ]
43
44# Filter for configs of no interest. They are old config names replaced by more
45# specific ones.
46CONFIGS_TO_FILTER = ['gpu', 'raster']
47
48# Template for gsutil uri.
49GOOGLE_STORAGE_URI_SCHEME = 'gs'
50URI_BUCKET = 'chromium-skia-gm'
51
52# Constants for optparse.
53USAGE_STRING = 'USAGE: %s [options]'
54HOWTO_STRING = """
55Feel free to revise PLATFORMS for your own needs. The default is the most common
56combination that we care most about. Platforms that did not run bench_pictures
57in the given revision range will not have corresponding outputs.
58Please check http://go/skpbench to choose a range that fits your needs.
59BENCH_UB and BENCH_LB can be changed to expand or narrow the permitted bench
60ranges without triggering buidbot alerts.
61"""
62HELP_STRING = """
63Outputs expectation picture bench ranges for the latest revisions for the given
64revision range. For instance, --rev_range=6000:6000 will return only bench
65ranges for the bots that ran bench_pictures at rev 6000; --rev-range=6000:7000
66may have multiple bench data points for each bench configuration, and the code
67returns bench data for the latest revision of all available (closer to 7000).
68""" + HOWTO_STRING
69
70OPTION_REVISION_RANGE = '--rev-range'
71OPTION_REVISION_RANGE_SHORT = '-r'
72# Bench bench representation algorithm flag.
73OPTION_REPRESENTATION_ALG = '--algorithm'
74OPTION_REPRESENTATION_ALG_SHORT = '-a'
75
76# List of valid representation algorithms.
77REPRESENTATION_ALGS = ['avg', 'min', 'med', '25th']
78
79def OutputSkpBenchExpectations(rev_min, rev_max, representation_alg):
80 """Reads skp bench data from google storage, and outputs expectations.
81
82 Ignores data with revisions outside [rev_min, rev_max] integer range. For
83 bench data with multiple revisions, we use higher revisions to calculate
84 expected bench values.
85 Uses the provided representation_alg for calculating bench representations.
86 """
87 expectation_dic = {}
88 uri = boto.storage_uri(URI_BUCKET, GOOGLE_STORAGE_URI_SCHEME)
89 for obj in uri.get_bucket():
90 # Filters out non-skp-bench files.
91 if (not obj.name.startswith('perfdata/Skia_') or
92 obj.name.find('_data_skp_') < 0):
93 continue
94 # Ignores uninterested platforms.
95 platform = obj.name.split('/')[1][5:] # Removes "Skia_" prefix.
96 if platform not in PLATFORMS:
97 continue
98 # Filters by revision.
99 for rev in range(rev_min, rev_max + 1):
100 if '_r%s_' % rev not in obj.name:
101 continue
102
103 contents = cStringIO.StringIO()
104 obj.get_file(contents)
105 for point in bench_util.parse('', contents.getvalue().split('\n'),
106 representation_alg):
107 if point.config in CONFIGS_TO_FILTER:
108 continue
109 # TODO(bensong): the filtering below is only needed during skp generation
110 # system transitioning. Change it once the new system (bench name starts
111 # with http) is stable for the switch-over, and delete it once we
112 # deprecate the old ones.
113 if point.bench.startswith('http'):
114 continue
115
116 key = '%s_%s_%s,%s-%s' % (point.bench, point.config, point.time_type,
117 platform, representation_alg)
118 # It is fine to have later revisions overwrite earlier benches, since we
119 # only use the latest bench within revision range to set expectations.
120 expectation_dic[key] = point.time
121 keys = expectation_dic.keys()
122 keys.sort()
123 for key in keys:
124 bench_val = expectation_dic[key]
125 # Prints out expectation lines.
bensong@google.comdc2dd2e2012-11-27 21:52:32 +0000126 print '%s,%.3f,%.3f,%.3f' % (key, bench_val, bench_val * BENCH_LB,
bensong@google.comfa1d4ea2012-11-27 17:30:26 +0000127 bench_val * BENCH_UB)
128
129def main():
130 """Parses flags and outputs expected Skia picture bench results."""
131 parser = optparse.OptionParser(USAGE_STRING % '%prog' + HELP_STRING)
132 parser.add_option(OPTION_REVISION_RANGE_SHORT, OPTION_REVISION_RANGE,
133 dest='rev_range',
134 help='(Mandatory) revision range separated by ":", e.g., 6000:6005')
135 parser.add_option(OPTION_REPRESENTATION_ALG_SHORT, OPTION_REPRESENTATION_ALG,
136 dest='alg', default='25th',
137 help=('Bench representation algorithm. One of '
138 '%s. Default to "25th".' % str(REPRESENTATION_ALGS)))
139 (options, args) = parser.parse_args()
140 if options.rev_range:
141 range_match = re.search('(\d+)\:(\d+)', options.rev_range)
142 if not range_match:
143 parser.error('Wrong format for rev-range [%s]' % options.rev_range)
144 else:
145 rev_min = int(range_match.group(1))
146 rev_max = int(range_match.group(2))
147 OutputSkpBenchExpectations(rev_min, rev_max, options.alg)
148 else:
149 parser.error('Please provide mandatory flag %s' % OPTION_REVISION_RANGE)
150
151
152if '__main__' == __name__:
153 main()