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

Side by Side Diff: tools/auto_bisect/bisect_perf_regression.py

Issue 645383002: Split RmTreeAndMkDir into two separate functions (refactoring). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove config for try job. Created 6 years, 2 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 | « no previous file | no next file » | 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 BUILD_RESULT_FAIL = 1 160 BUILD_RESULT_FAIL = 1
161 BUILD_RESULT_SKIPPED = 2 161 BUILD_RESULT_SKIPPED = 2
162 162
163 # Maximum time in seconds to wait after posting build request to the try server. 163 # Maximum time in seconds to wait after posting build request to the try server.
164 # TODO: Change these values based on the actual time taken by buildbots on 164 # TODO: Change these values based on the actual time taken by buildbots on
165 # the try server. 165 # the try server.
166 MAX_MAC_BUILD_TIME = 14400 166 MAX_MAC_BUILD_TIME = 14400
167 MAX_WIN_BUILD_TIME = 14400 167 MAX_WIN_BUILD_TIME = 14400
168 MAX_LINUX_BUILD_TIME = 14400 168 MAX_LINUX_BUILD_TIME = 14400
169 169
170 # The confidence percentage at which confidence can be consider "high". 170 # The percentage at which confidence is considered high.
171 HIGH_CONFIDENCE = 95 171 HIGH_CONFIDENCE = 95
172 172
173 # Patch template to add a new file, DEPS.sha under src folder. 173 # Patch template to add a new file, DEPS.sha under src folder.
174 # This file contains SHA1 value of the DEPS changes made while bisecting 174 # This file contains SHA1 value of the DEPS changes made while bisecting
175 # dependency repositories. This patch send along with DEPS patch to try server. 175 # dependency repositories. This patch send along with DEPS patch to try server.
176 # When a build requested is posted with a patch, bisect builders on try server, 176 # When a build requested is posted with a patch, bisect builders on try server,
177 # once build is produced, it reads SHA value from this file and appends it 177 # once build is produced, it reads SHA value from this file and appends it
178 # to build archive filename. 178 # to build archive filename.
179 DEPS_SHA_PATCH = """diff --git DEPS.sha DEPS.sha 179 DEPS_SHA_PATCH = """diff --git DEPS.sha DEPS.sha
180 new file mode 100644 180 new file mode 100644
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 Returns: 1242 Returns:
1243 Path to backup or restored location as string. otherwise None if it fails. 1243 Path to backup or restored location as string. otherwise None if it fails.
1244 """ 1244 """
1245 build_dir = os.path.abspath( 1245 build_dir = os.path.abspath(
1246 builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) 1246 builder.GetBuildOutputDirectory(self.opts, self.src_cwd))
1247 source_dir = os.path.join(build_dir, build_type) 1247 source_dir = os.path.join(build_dir, build_type)
1248 destination_dir = os.path.join(build_dir, '%s.bak' % build_type) 1248 destination_dir = os.path.join(build_dir, '%s.bak' % build_type)
1249 if restore: 1249 if restore:
1250 source_dir, destination_dir = destination_dir, source_dir 1250 source_dir, destination_dir = destination_dir, source_dir
1251 if os.path.exists(source_dir): 1251 if os.path.exists(source_dir):
1252 RmTreeAndMkDir(destination_dir, skip_makedir=True) 1252 RemoveDirectoryTree(destination_dir)
1253 shutil.move(source_dir, destination_dir) 1253 shutil.move(source_dir, destination_dir)
1254 return destination_dir 1254 return destination_dir
1255 return None 1255 return None
1256 1256
1257 def GetBuildArchiveForRevision(self, revision, gs_bucket, target_arch, 1257 def GetBuildArchiveForRevision(self, revision, gs_bucket, target_arch,
1258 patch_sha, out_dir): 1258 patch_sha, out_dir):
1259 """Checks and downloads build archive for a given revision. 1259 """Checks and downloads build archive for a given revision.
1260 1260
1261 Checks for build archive with Git hash or SVN revision. If either of the 1261 Checks for build archive with Git hash or SVN revision. If either of the
1262 file exists, then downloads the archive file. 1262 file exists, then downloads the archive file.
(...skipping 19 matching lines...) Expand all
1282 # Source archive file path on cloud storage using SVN revision. 1282 # Source archive file path on cloud storage using SVN revision.
1283 source_file = GetRemoteBuildPath( 1283 source_file = GetRemoteBuildPath(
1284 commit_position, self.opts.target_platform, target_arch, patch_sha) 1284 commit_position, self.opts.target_platform, target_arch, patch_sha)
1285 return FetchFromCloudStorage(gs_bucket, source_file, out_dir) 1285 return FetchFromCloudStorage(gs_bucket, source_file, out_dir)
1286 return downloaded_archive 1286 return downloaded_archive
1287 1287
1288 def DownloadCurrentBuild(self, revision, depot, build_type='Release'): 1288 def DownloadCurrentBuild(self, revision, depot, build_type='Release'):
1289 """Downloads the build archive for the given revision. 1289 """Downloads the build archive for the given revision.
1290 1290
1291 Args: 1291 Args:
1292 revision: The Git revision to download or build. 1292 revision: The git revision to download or build.
1293 build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) 1293 depot: The name of a dependency repository. Should be in DEPOT_NAMES.
1294 patch: A DEPS patch (used while bisecting 3rd party repositories). 1294 build_type: Target build type, e.g. Release', 'Debug', 'Release_x64' etc.
1295 1295
1296 Returns: 1296 Returns:
1297 True if download succeeds, otherwise False. 1297 True if download succeeds, otherwise False.
1298 """ 1298 """
1299 patch = None 1299 patch = None
1300 patch_sha = None 1300 patch_sha = None
1301 if depot != 'chromium': 1301 if depot != 'chromium':
1302 # Create a DEPS patch with new revision for dependency repository. 1302 # Create a DEPS patch with new revision for dependency repository.
1303 revision, patch = self.CreateDEPSPatch(depot, revision) 1303 revision, patch = self.CreateDEPSPatch(depot, revision)
1304 1304
1305 if patch: 1305 if patch:
1306 # Get the SHA of the DEPS changes patch. 1306 # Get the SHA of the DEPS changes patch.
1307 patch_sha = GetSHA1HexDigest(patch) 1307 patch_sha = GetSHA1HexDigest(patch)
1308 1308
1309 # Update the DEPS changes patch with a patch to create a new file named 1309 # Update the DEPS changes patch with a patch to create a new file named
1310 # 'DEPS.sha' and add patch_sha evaluated above to it. 1310 # 'DEPS.sha' and add patch_sha evaluated above to it.
1311 patch = '%s\n%s' % (patch, DEPS_SHA_PATCH % {'deps_sha': patch_sha}) 1311 patch = '%s\n%s' % (patch, DEPS_SHA_PATCH % {'deps_sha': patch_sha})
1312 1312
1313 # Get Build output directory 1313 # Get build output directory.
1314 abs_build_dir = os.path.abspath( 1314 build_dir = builder.GetBuildOutputDirectory(self.opts, self.src_cwd)
1315 builder.GetBuildOutputDirectory(self.opts, self.src_cwd)) 1315 abs_build_dir = os.path.abspath(build_dir)
1316 1316
1317 fetch_build_func = lambda: self.GetBuildArchiveForRevision( 1317 fetch_build_func = lambda: self.GetBuildArchiveForRevision(
1318 revision, self.opts.gs_bucket, self.opts.target_arch, 1318 revision, self.opts.gs_bucket, self.opts.target_arch,
1319 patch_sha, abs_build_dir) 1319 patch_sha, abs_build_dir)
1320 1320
1321 # Downloaded archive file path, downloads build archive for given revision. 1321 # Downloaded archive file path, downloads build archive for given revision.
1322 downloaded_file = fetch_build_func() 1322 downloaded_file = fetch_build_func()
1323 1323
1324 # When build archive doesn't exists, post a build request to tryserver 1324 # When build archive doesn't exists, post a build request to tryserver
1325 # and wait for the build to be produced. 1325 # and wait for the build to be produced.
1326 if not downloaded_file: 1326 if not downloaded_file:
1327 downloaded_file = self.PostBuildRequestAndWait( 1327 downloaded_file = self.PostBuildRequestAndWait(
1328 revision, fetch_build=fetch_build_func, patch=patch) 1328 revision, fetch_build=fetch_build_func, patch=patch)
1329 if not downloaded_file: 1329 if not downloaded_file:
1330 return False 1330 return False
1331 1331
1332 # Generic name for the archive, created when archive file is extracted. 1332 # Generic name for the archive, created when archive file is extracted.
1333 output_dir = os.path.join( 1333 output_dir = os.path.join(
1334 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch)) 1334 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch))
1335
1335 # Unzip build archive directory. 1336 # Unzip build archive directory.
1336 try: 1337 try:
1337 RmTreeAndMkDir(output_dir, skip_makedir=True) 1338 RemoveDirectoryTree(output_dir)
1338 self.BackupOrRestoreOutputDirectory(restore=False) 1339 self.BackupOrRestoreOutputDirectory(restore=False)
1339 # Build output directory based on target(e.g. out/Release, out/Debug). 1340 # Build output directory based on target(e.g. out/Release, out/Debug).
1340 target_build_output_dir = os.path.join(abs_build_dir, build_type) 1341 target_build_output_dir = os.path.join(abs_build_dir, build_type)
1341 ExtractZip(downloaded_file, abs_build_dir) 1342 ExtractZip(downloaded_file, abs_build_dir)
1342 if not os.path.exists(output_dir): 1343 if not os.path.exists(output_dir):
1343 # Due to recipe changes, the builds extract folder contains 1344 # Due to recipe changes, the builds extract folder contains
1344 # out/Release instead of full-build-<platform>/Release. 1345 # out/Release instead of full-build-<platform>/Release.
1345 if os.path.exists(os.path.join(abs_build_dir, 'out', build_type)): 1346 if os.path.exists(os.path.join(abs_build_dir, 'out', build_type)):
1346 output_dir = os.path.join(abs_build_dir, 'out', build_type) 1347 output_dir = os.path.join(abs_build_dir, 'out', build_type)
1347 else: 1348 else:
1348 raise IOError('Missing extracted folder %s ' % output_dir) 1349 raise IOError('Missing extracted folder %s ' % output_dir)
1349 1350
1350 print 'Moving build from %s to %s' % ( 1351 print 'Moving build from %s to %s' % (
1351 output_dir, target_build_output_dir) 1352 output_dir, target_build_output_dir)
1352 shutil.move(output_dir, target_build_output_dir) 1353 shutil.move(output_dir, target_build_output_dir)
1353 return True 1354 return True
1354 except Exception as e: 1355 except Exception as e:
1355 print 'Something went wrong while extracting archive file: %s' % e 1356 print 'Something went wrong while extracting archive file: %s' % e
1356 self.BackupOrRestoreOutputDirectory(restore=True) 1357 self.BackupOrRestoreOutputDirectory(restore=True)
1357 # Cleanup any leftovers from unzipping. 1358 # Cleanup any leftovers from unzipping.
1358 if os.path.exists(output_dir): 1359 if os.path.exists(output_dir):
1359 RmTreeAndMkDir(output_dir, skip_makedir=True) 1360 RemoveDirectoryTree(output_dir)
1360 finally: 1361 finally:
1361 # Delete downloaded archive 1362 # Delete downloaded archive
1362 if os.path.exists(downloaded_file): 1363 if os.path.exists(downloaded_file):
1363 os.remove(downloaded_file) 1364 os.remove(downloaded_file)
1364 return False 1365 return False
1365 1366
1366 def PostBuildRequestAndWait(self, git_revision, fetch_build, patch=None): 1367 def PostBuildRequestAndWait(self, git_revision, fetch_build, patch=None):
1367 """POSTs the build request job to the try server instance. 1368 """POSTs the build request job to the try server instance.
1368 1369
1369 A try job build request is posted to tryserver.chromium.perf master, 1370 A try job build request is posted to tryserver.chromium.perf master,
(...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after
2882 opts: The options parsed from the command line. 2883 opts: The options parsed from the command line.
2883 2884
2884 Returns: 2885 Returns:
2885 True if the platform and build system are supported. 2886 True if the platform and build system are supported.
2886 """ 2887 """
2887 # Haven't tested the script out on any other platforms yet. 2888 # Haven't tested the script out on any other platforms yet.
2888 supported = ['posix', 'nt'] 2889 supported = ['posix', 'nt']
2889 return os.name in supported 2890 return os.name in supported
2890 2891
2891 2892
2892 def RmTreeAndMkDir(path_to_dir, skip_makedir=False): 2893 def RemakeDirectoryTree(path_to_dir):
2893 """Removes the directory tree specified, and then creates an empty 2894 """Removes a directory tree and replaces it with an empty one.
2894 directory in the same location (if not specified to skip).
2895 2895
2896 Args: 2896 Returns True if successful, False otherwise.
2897 path_to_dir: Path to the directory tree. 2897 """
2898 skip_makedir: Whether to skip creating empty directory, default is False. 2898 if not RemoveDirectoryTree(path_to_dir):
2899 return False
2900 return MaybeMakeDirectory(path_to_dir)
2899 2901
2900 Returns: 2902
2901 True if successful, False if an error occurred. 2903 def RemoveDirectoryTree(path_to_dir):
2902 """ 2904 """Removes a directory tree. Returns True if successful or False otherwise."""
2903 try: 2905 try:
2904 if os.path.exists(path_to_dir): 2906 if os.path.exists(path_to_dir):
2905 shutil.rmtree(path_to_dir) 2907 shutil.rmtree(path_to_dir)
2906 except OSError, e: 2908 except OSError, e:
2907 if e.errno != errno.ENOENT: 2909 if e.errno != errno.ENOENT:
2908 return False 2910 return False
2909
2910 if not skip_makedir:
2911 return MaybeMakeDirectory(path_to_dir)
2912
2913 return True 2911 return True
2914 2912
2915 2913
2916 def RemoveBuildFiles(build_type): 2914 def RemoveBuildFiles(build_type):
2917 """Removes build files from previous runs.""" 2915 """Removes build files from previous runs."""
2918 if RmTreeAndMkDir(os.path.join('out', build_type)): 2916 if RemakeDirectoryTree(os.path.join('out', build_type)):
2919 if RmTreeAndMkDir(os.path.join('build', build_type)): 2917 if RemakeDirectoryTree(os.path.join('build', build_type)):
RobertoCN 2014/10/14 18:31:34 Wouldn't an 'and' look better here as opposed to t
qyearsley 2014/10/14 18:36:26 IMO, "and" would definitely be better here if the
2920 return True 2918 return True
2921 return False 2919 return False
2922 2920
2923 2921
2924 class BisectOptions(object): 2922 class BisectOptions(object):
2925 """Options to be used when running bisection.""" 2923 """Options to be used when running bisection."""
2926 def __init__(self): 2924 def __init__(self):
2927 super(BisectOptions, self).__init__() 2925 super(BisectOptions, self).__init__()
2928 2926
2929 self.target_platform = 'chromium' 2927 self.target_platform = 'chromium'
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 # bugs. If you change this, please update the perf dashboard as well. 3255 # bugs. If you change this, please update the perf dashboard as well.
3258 bisect_utils.OutputAnnotationStepStart('Results') 3256 bisect_utils.OutputAnnotationStepStart('Results')
3259 print 'Error: %s' % e.message 3257 print 'Error: %s' % e.message
3260 if opts.output_buildbot_annotations: 3258 if opts.output_buildbot_annotations:
3261 bisect_utils.OutputAnnotationStepClosed() 3259 bisect_utils.OutputAnnotationStepClosed()
3262 return 1 3260 return 1
3263 3261
3264 3262
3265 if __name__ == '__main__': 3263 if __name__ == '__main__':
3266 sys.exit(main()) 3264 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698