Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: tools/bisect-perf-regression.py

Issue 12261026: Added separate checkout and config file generation to bisect script (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes from review. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/PRESUBMIT.py ('k') | tools/run-bisect-perf-regression.cfg » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Performance Test Bisect Tool 6 """Performance Test Bisect Tool
7 7
8 This script bisects a series of changelists using binary search. It starts at 8 This script bisects a series of changelists using binary search. It starts at
9 a bad revision where a performance metric has regressed, and asks for a last 9 a bad revision where a performance metric has regressed, and asks for a last
10 known-good revision. It will then binary search across this revision range by 10 known-good revision. It will then binary search across this revision range by
(...skipping 17 matching lines...) Expand all
28 An example usage (using git hashes): 28 An example usage (using git hashes):
29 29
30 ./tools/bisect-perf-regression.py -c\ 30 ./tools/bisect-perf-regression.py -c\
31 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\ 31 "out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\
32 -g 1f6e67861535121c5c819c16a666f2436c207e7b\ 32 -g 1f6e67861535121c5c819c16a666f2436c207e7b\
33 -b b732f23b4f81c382db0b23b9035f3dadc7d925bb\ 33 -b b732f23b4f81c382db0b23b9035f3dadc7d925bb\
34 -m shutdown/simple-user-quit 34 -m shutdown/simple-user-quit
35 35
36 """ 36 """
37 37
38 38 import errno
39 import imp
40 import optparse
41 import os
39 import re 42 import re
40 import os 43 import shlex
41 import imp 44 import subprocess
42 import sys 45 import sys
43 import shlex
44 import optparse
45 import subprocess
46 46
47 47
48 # The additional repositories that might need to be bisected. 48 # The additional repositories that might need to be bisected.
49 # If the repository has any dependant repositories (such as skia/src needs 49 # If the repository has any dependant repositories (such as skia/src needs
50 # skia/include and skia/gyp to be updated), specify them in the 'depends' 50 # skia/include and skia/gyp to be updated), specify them in the 'depends'
51 # so that they're synced appropriately. 51 # so that they're synced appropriately.
52 # Format is: 52 # Format is:
53 # src: path to the working directory. 53 # src: path to the working directory.
54 # recurse: True if this repositry will get bisected. 54 # recurse: True if this repositry will get bisected.
55 # depends: A list of other repositories that are actually part of the same 55 # depends: A list of other repositories that are actually part of the same
(...skipping 26 matching lines...) Expand all
82 "recurse" : False, 82 "recurse" : False,
83 "svn" : "http://skia.googlecode.com/svn/trunk/gyp", 83 "svn" : "http://skia.googlecode.com/svn/trunk/gyp",
84 "depends" : None 84 "depends" : None
85 } 85 }
86 } 86 }
87 87
88 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() 88 DEPOT_NAMES = DEPOT_DEPS_NAME.keys()
89 89
90 FILE_DEPS_GIT = '.DEPS.git' 90 FILE_DEPS_GIT = '.DEPS.git'
91 91
92 GCLIENT_SPEC = """
93 solutions = [
94 { "name" : "src",
95 "url" : "https://chromium.googlesource.com/chromium/src.git",
96 "deps_file" : ".DEPS.git",
97 "managed" : True,
98 "custom_deps" : {
99 },
100 "safesync_url": "",
101 },
102 { "name" : "src-internal",
103 "url" : "ssh://gerrit-int.chromium.org:29419/" +
104 "chrome/src-internal.git",
105 "deps_file" : ".DEPS.git",
106 },
107 ]
108 """
109 GCLIENT_SPEC = ''.join([l for l in GCLIENT_SPEC.splitlines()])
110
92 111
93 112
94 def IsStringFloat(string_to_check): 113 def IsStringFloat(string_to_check):
95 """Checks whether or not the given string can be converted to a floating 114 """Checks whether or not the given string can be converted to a floating
96 point number. 115 point number.
97 116
98 Args: 117 Args:
99 string_to_check: Input string to check if it can be converted to a float. 118 string_to_check: Input string to check if it can be converted to a float.
100 119
101 Returns: 120 Returns:
(...skipping 26 matching lines...) Expand all
128 147
129 def OutputAnnotationStepStart(name): 148 def OutputAnnotationStepStart(name):
130 """Outputs appropriate annotation to signal the start of a step to 149 """Outputs appropriate annotation to signal the start of a step to
131 a trybot. 150 a trybot.
132 151
133 Args: 152 Args:
134 name: The name of the step. 153 name: The name of the step.
135 """ 154 """
136 print '@@@SEED_STEP %s@@@' % name 155 print '@@@SEED_STEP %s@@@' % name
137 print '@@@STEP_CURSOR %s@@@' % name 156 print '@@@STEP_CURSOR %s@@@' % name
138 print '@@@STEP_STARTED@@@' 157 print '@@@STEP_STARTED@@@'
Mike Stip (use stip instead) 2013/02/21 02:15:32 check if this shows up OK on the waterfall. if it'
shatch 2013/02/21 16:58:08 Seems to show up ok on my local buildbot.
139 158
140 159
141 def OutputAnnotationStepClosed(): 160 def OutputAnnotationStepClosed():
142 """Outputs appropriate annotation to signal the closing of a step to 161 """Outputs appropriate annotation to signal the closing of a step to
143 a trybot.""" 162 a trybot."""
144 print '@@@STEP_CLOSED@@@' 163 print '@@@STEP_CLOSED@@@'
145 164
146 165
147 def RunProcess(command): 166 def RunProcess(command):
148 """Run an arbitrary command, returning its output and return code. 167 """Run an arbitrary command, returning its output and return code.
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 """ 1146 """
1128 1147
1129 (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree']) 1148 (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree'])
1130 1149
1131 if output.strip() == 'true': 1150 if output.strip() == 'true':
1132 return GitSourceControl() 1151 return GitSourceControl()
1133 1152
1134 return None 1153 return None
1135 1154
1136 1155
1156 def CreateAndChangeToSourceDirectory(working_directory):
1157 """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If
1158 the function is successful, the current working directory will change to that
1159 of the new 'bisect' directory.
1160
1161 Returns:
1162 True if the directory was successfully created (or already existed).
1163 """
1164 cwd = os.getcwd()
1165 os.chdir(working_directory)
1166 try:
1167 os.mkdir('bisect')
1168 except OSError, e:
1169 if e.errno != errno.EEXIST:
1170 return False
1171 os.chdir('bisect')
1172 return True
1173
1174
1175 def RunGClient(params):
1176 """Runs gclient with the specified parameters.
1177
1178 Args:
1179 params: A list of parameters to pass to gclient.
1180
1181 Returns:
1182 The return code of the call.
1183 """
1184 cmd = ['gclient'] + params
1185 return subprocess.call(cmd)
1186
1187
1188 def RunGClientAndCreateConfig():
1189 """Runs gclient and creates a config containing both src and src-internal.
1190
1191 Returns:
1192 The return code of the call.
1193 """
1194 return_code = RunGClient(
1195 ['config', '--spec=%s' % GCLIENT_SPEC, '--git-deps'])
1196 return return_code
1197
1198
1199 def RunGClientAndSync():
1200 """Runs gclient and does a normal sync.
1201
1202 Returns:
1203 The return code of the call.
1204 """
1205 return RunGClient(['sync'])
1206
1207
1208 def SetupGitDepot(output_buildbot_annotations):
1209 """Sets up the depot for the bisection. The depot will be located in a
1210 subdirectory called 'bisect'.
1211
1212 Returns:
1213 True if gclient successfully created the config file and did a sync, False
1214 otherwise.
1215 """
1216 name = 'Setting up Bisection Depot'
1217
1218 if output_buildbot_annotations:
Mike Stip (use stip instead) 2013/02/21 02:15:32 probably want to use OutputAnnotationStepStart() h
shatch 2013/02/21 16:58:08 Done.
1219 print '@@@SEED_STEP %s@@@' % name
1220 print '@@@STEP_CURSOR %s@@@' % name
1221 print '@@@STEP_STARTED@@@'
1222
1223 passed = False
1224
1225 if not RunGClientAndCreateConfig():
1226 if not RunGClientAndSync():
1227 passed = True
1228
1229 if output_buildbot_annotations:
1230 print
Mike Stip (use stip instead) 2013/02/21 02:15:32 OutputAnnotationStepClosed()
shatch 2013/02/21 16:58:08 Done.
1231 print '@@@STEP_CLOSED@@@'
1232
1233 return passed
1234
1235
1137 def main(): 1236 def main():
1138 1237
1139 usage = ('%prog [options] [-- chromium-options]\n' 1238 usage = ('%prog [options] [-- chromium-options]\n'
1140 'Perform binary search on revision history to find a minimal ' 1239 'Perform binary search on revision history to find a minimal '
1141 'range of revisions where a peformance metric regressed.\n') 1240 'range of revisions where a peformance metric regressed.\n')
1142 1241
1143 parser = optparse.OptionParser(usage=usage) 1242 parser = optparse.OptionParser(usage=usage)
1144 1243
1145 parser.add_option('-c', '--command', 1244 parser.add_option('-c', '--command',
1146 type='str', 1245 type='str',
1147 help='A command to execute your performance test at' + 1246 help='A command to execute your performance test at' +
1148 ' each point in the bisection.') 1247 ' each point in the bisection.')
1149 parser.add_option('-b', '--bad_revision', 1248 parser.add_option('-b', '--bad_revision',
1150 type='str', 1249 type='str',
1151 help='A bad revision to start bisection. ' + 1250 help='A bad revision to start bisection. ' +
1152 'Must be later than good revision. May be either a git' + 1251 'Must be later than good revision. May be either a git' +
1153 ' or svn revision.') 1252 ' or svn revision.')
1154 parser.add_option('-g', '--good_revision', 1253 parser.add_option('-g', '--good_revision',
1155 type='str', 1254 type='str',
1156 help='A revision to start bisection where performance' + 1255 help='A revision to start bisection where performance' +
1157 ' test is known to pass. Must be earlier than the ' + 1256 ' test is known to pass. Must be earlier than the ' +
1158 'bad revision. May be either a git or svn revision.') 1257 'bad revision. May be either a git or svn revision.')
1159 parser.add_option('-m', '--metric', 1258 parser.add_option('-m', '--metric',
1160 type='str', 1259 type='str',
1161 help='The desired metric to bisect on. For example ' + 1260 help='The desired metric to bisect on. For example ' +
1162 '"vm_rss_final_b/vm_rss_f_b"') 1261 '"vm_rss_final_b/vm_rss_f_b"')
1262 parser.add_option('-w', '--working_directory',
1263 type='str',
1264 help='Path to the working directory where the script will '
1265 'do an initial checkout of the chromium depot. The '
1266 'files will be placed in a subdirectory "bisect" under '
1267 'working_directory and that will be used to perform the '
1268 'bisection. This parameter is optional, if it is not '
1269 'supplied, the script will work from the current depot.')
1163 parser.add_option('--use_goma', 1270 parser.add_option('--use_goma',
1164 action="store_true", 1271 action="store_true",
1165 help='Add a bunch of extra threads for goma.') 1272 help='Add a bunch of extra threads for goma.')
1166 parser.add_option('--output_buildbot_annotations', 1273 parser.add_option('--output_buildbot_annotations',
1167 action="store_true", 1274 action="store_true",
1168 help='Add extra annotation output for buildbot.') 1275 help='Add extra annotation output for buildbot.')
1169 parser.add_option('--debug_ignore_build', 1276 parser.add_option('--debug_ignore_build',
1170 action="store_true", 1277 action="store_true",
1171 help='DEBUG: Don\'t perform builds.') 1278 help='DEBUG: Don\'t perform builds.')
1172 parser.add_option('--debug_ignore_sync', 1279 parser.add_option('--debug_ignore_sync',
(...skipping 27 matching lines...) Expand all
1200 print 1307 print
1201 parser.print_help() 1308 parser.print_help()
1202 return 1 1309 return 1
1203 1310
1204 # Haven't tested the script out on any other platforms yet. 1311 # Haven't tested the script out on any other platforms yet.
1205 if not os.name in ['posix']: 1312 if not os.name in ['posix']:
1206 print "Sorry, this platform isn't supported yet." 1313 print "Sorry, this platform isn't supported yet."
1207 print 1314 print
1208 return 1 1315 return 1
1209 1316
1317 metric_values = opts.metric.split('/')
1318 if len(metric_values) != 2:
1319 print "Invalid metric specified: [%s]" % (opts.metric,)
1320 print
1321 return 1
1322
1323 if opts.working_directory:
1324 if not CreateAndChangeToSourceDirectory(opts.working_directory):
1325 print 'Error: Could not create bisect directory.'
1326 print
1327 return 1
1328
1329 if not SetupGitDepot(opts.output_buildbot_annotations):
1330 print 'Error: Failed to grab source.'
1331 print
1332 return 1
1333
1334 os.chdir(os.path.join(os.getcwd(), 'src'))
1210 1335
1211 # Check what source control method they're using. Only support git workflow 1336 # Check what source control method they're using. Only support git workflow
1212 # at the moment. 1337 # at the moment.
1213 source_control = DetermineAndCreateSourceControl() 1338 source_control = DetermineAndCreateSourceControl()
1214 1339
1215 if not source_control: 1340 if not source_control:
1216 print "Sorry, only the git workflow is supported at the moment." 1341 print "Sorry, only the git workflow is supported at the moment."
1217 print 1342 print
1218 return 1 1343 return 1
1219 1344
1220 # gClient sync seems to fail if you're not in master branch. 1345 # gClient sync seems to fail if you're not in master branch.
1221 if not source_control.IsInProperBranch() and not opts.debug_ignore_sync: 1346 if not source_control.IsInProperBranch() and not opts.debug_ignore_sync:
1222 print "You must switch to master branch to run bisection." 1347 print "You must switch to master branch to run bisection."
1223 print 1348 print
1224 return 1 1349 return 1
1225 1350
1226 metric_values = opts.metric.split('/')
1227 if len(metric_values) < 2:
1228 print "Invalid metric specified: [%s]" % (opts.metric,)
1229 print
1230 return 1
1231
1232
1233 bisect_test = BisectPerformanceMetrics(source_control, opts) 1351 bisect_test = BisectPerformanceMetrics(source_control, opts)
1234 bisect_results = bisect_test.Run(opts.command, 1352 bisect_results = bisect_test.Run(opts.command,
1235 opts.bad_revision, 1353 opts.bad_revision,
1236 opts.good_revision, 1354 opts.good_revision,
1237 metric_values) 1355 metric_values)
1238 1356
1239 if not(bisect_results['error']): 1357 if not(bisect_results['error']):
1240 bisect_test.FormatAndPrintResults(bisect_results) 1358 bisect_test.FormatAndPrintResults(bisect_results)
1241 return 0 1359 return 0
1242 else: 1360 else:
1243 print 'Error: ' + bisect_results['error'] 1361 print 'Error: ' + bisect_results['error']
1244 print 1362 print
1245 return 1 1363 return 1
1246 1364
1247 if __name__ == '__main__': 1365 if __name__ == '__main__':
1248 sys.exit(main()) 1366 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/PRESUBMIT.py ('k') | tools/run-bisect-perf-regression.cfg » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698