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

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

Issue 661803003: Revert of Refactor source_control.py and add a test. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 | tools/auto_bisect/bisect_perf_regression_test.py » ('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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 import zipfile 47 import zipfile
48 48
49 sys.path.append(os.path.join( 49 sys.path.append(os.path.join(
50 os.path.dirname(__file__), os.path.pardir, 'telemetry')) 50 os.path.dirname(__file__), os.path.pardir, 'telemetry'))
51 51
52 from bisect_results import BisectResults 52 from bisect_results import BisectResults
53 import bisect_utils 53 import bisect_utils
54 import builder 54 import builder
55 import math_utils 55 import math_utils
56 import request_build 56 import request_build
57 import source_control 57 import source_control as source_control_module
58 from telemetry.util import cloud_storage 58 from telemetry.util import cloud_storage
59 59
60 # Below is the map of "depot" names to information about each depot. Each depot 60 # Below is the map of "depot" names to information about each depot. Each depot
61 # is a repository, and in the process of bisecting, revision ranges in these 61 # is a repository, and in the process of bisecting, revision ranges in these
62 # repositories may also be bisected. 62 # repositories may also be bisected.
63 # 63 #
64 # Each depot information dictionary may contain: 64 # Each depot information dictionary may contain:
65 # src: Path to the working directory. 65 # src: Path to the working directory.
66 # recurse: True if this repository will get bisected. 66 # recurse: True if this repository will get bisected.
67 # depends: A list of other repositories that are actually part of the same 67 # depends: A list of other repositories that are actually part of the same
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH]) 950 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH])
951 951
952 952
953 class BisectPerformanceMetrics(object): 953 class BisectPerformanceMetrics(object):
954 """This class contains functionality to perform a bisection of a range of 954 """This class contains functionality to perform a bisection of a range of
955 revisions to narrow down where performance regressions may have occurred. 955 revisions to narrow down where performance regressions may have occurred.
956 956
957 The main entry-point is the Run method. 957 The main entry-point is the Run method.
958 """ 958 """
959 959
960 def __init__(self, opts): 960 def __init__(self, source_control, opts):
961 super(BisectPerformanceMetrics, self).__init__() 961 super(BisectPerformanceMetrics, self).__init__()
962 962
963 self.opts = opts 963 self.opts = opts
964 self.source_control = source_control
964 965
965 # The src directory here is NOT the src/ directory for the repository 966 # The src directory here is NOT the src/ directory for the repository
966 # where the bisect script is running from. Instead, it's the src/ directory 967 # where the bisect script is running from. Instead, it's the src/ directory
967 # inside the bisect/ directory which is created before running. 968 # inside the bisect/ directory which is created before running.
968 self.src_cwd = os.getcwd() 969 self.src_cwd = os.getcwd()
969 970
970 self.depot_registry = DepotDirectoryRegistry(self.src_cwd) 971 self.depot_registry = DepotDirectoryRegistry(self.src_cwd)
971 self.cleanup_commands = [] 972 self.cleanup_commands = []
972 self.warnings = [] 973 self.warnings = []
973 self.builder = builder.Builder.FromOpts(opts) 974 self.builder = builder.Builder.FromOpts(opts)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 assert not return_code, ('An error occurred while running ' 1007 assert not return_code, ('An error occurred while running '
1007 '"%s"' % ' '.join(cmd)) 1008 '"%s"' % ' '.join(cmd))
1008 1009
1009 os.chdir(cwd) 1010 os.chdir(cwd)
1010 1011
1011 revision_work_list = list(set( 1012 revision_work_list = list(set(
1012 [int(o) for o in output.split('\n') if bisect_utils.IsStringInt(o)])) 1013 [int(o) for o in output.split('\n') if bisect_utils.IsStringInt(o)]))
1013 revision_work_list = sorted(revision_work_list, reverse=True) 1014 revision_work_list = sorted(revision_work_list, reverse=True)
1014 else: 1015 else:
1015 cwd = self.depot_registry.GetDepotDir(depot) 1016 cwd = self.depot_registry.GetDepotDir(depot)
1016 revision_work_list = source_control.GetRevisionList(bad_revision, 1017 revision_work_list = self.source_control.GetRevisionList(bad_revision,
1017 good_revision, cwd=cwd) 1018 good_revision, cwd=cwd)
1018 1019
1019 return revision_work_list 1020 return revision_work_list
1020 1021
1021 def _GetV8BleedingEdgeFromV8TrunkIfMappable(self, revision): 1022 def _GetV8BleedingEdgeFromV8TrunkIfMappable(self, revision):
1022 commit_position = source_control.GetCommitPosition(revision) 1023 commit_position = self.source_control.GetCommitPosition(revision)
1023 1024
1024 if bisect_utils.IsStringInt(commit_position): 1025 if bisect_utils.IsStringInt(commit_position):
1025 # V8 is tricky to bisect, in that there are only a few instances when 1026 # V8 is tricky to bisect, in that there are only a few instances when
1026 # we can dive into bleeding_edge and get back a meaningful result. 1027 # we can dive into bleeding_edge and get back a meaningful result.
1027 # Try to detect a V8 "business as usual" case, which is when: 1028 # Try to detect a V8 "business as usual" case, which is when:
1028 # 1. trunk revision N has description "Version X.Y.Z" 1029 # 1. trunk revision N has description "Version X.Y.Z"
1029 # 2. bleeding_edge revision (N-1) has description "Prepare push to 1030 # 2. bleeding_edge revision (N-1) has description "Prepare push to
1030 # trunk. Now working on X.Y.(Z+1)." 1031 # trunk. Now working on X.Y.(Z+1)."
1031 # 1032 #
1032 # As of 01/24/2014, V8 trunk descriptions are formatted: 1033 # As of 01/24/2014, V8 trunk descriptions are formatted:
1033 # "Version 3.X.Y (based on bleeding_edge revision rZ)" 1034 # "Version 3.X.Y (based on bleeding_edge revision rZ)"
1034 # So we can just try parsing that out first and fall back to the old way. 1035 # So we can just try parsing that out first and fall back to the old way.
1035 v8_dir = self.depot_registry.GetDepotDir('v8') 1036 v8_dir = self.depot_registry.GetDepotDir('v8')
1036 v8_bleeding_edge_dir = self.depot_registry.GetDepotDir('v8_bleeding_edge') 1037 v8_bleeding_edge_dir = self.depot_registry.GetDepotDir('v8_bleeding_edge')
1037 1038
1038 revision_info = source_control.QueryRevisionInfo(revision, cwd=v8_dir) 1039 revision_info = self.source_control.QueryRevisionInfo(revision,
1040 cwd=v8_dir)
1039 1041
1040 version_re = re.compile("Version (?P<values>[0-9,.]+)") 1042 version_re = re.compile("Version (?P<values>[0-9,.]+)")
1041 1043
1042 regex_results = version_re.search(revision_info['subject']) 1044 regex_results = version_re.search(revision_info['subject'])
1043 1045
1044 if regex_results: 1046 if regex_results:
1045 git_revision = None 1047 git_revision = None
1046 1048
1047 # Look for "based on bleeding_edge" and parse out revision 1049 # Look for "based on bleeding_edge" and parse out revision
1048 if 'based on bleeding_edge' in revision_info['subject']: 1050 if 'based on bleeding_edge' in revision_info['subject']:
1049 try: 1051 try:
1050 bleeding_edge_revision = revision_info['subject'].split( 1052 bleeding_edge_revision = revision_info['subject'].split(
1051 'bleeding_edge revision r')[1] 1053 'bleeding_edge revision r')[1]
1052 bleeding_edge_revision = int(bleeding_edge_revision.split(')')[0]) 1054 bleeding_edge_revision = int(bleeding_edge_revision.split(')')[0])
1053 git_revision = source_control.ResolveToRevision( 1055 git_revision = self.source_control.ResolveToRevision(
1054 bleeding_edge_revision, 'v8_bleeding_edge', DEPOT_DEPS_NAME, 1, 1056 bleeding_edge_revision, 'v8_bleeding_edge', DEPOT_DEPS_NAME, 1,
1055 cwd=v8_bleeding_edge_dir) 1057 cwd=v8_bleeding_edge_dir)
1056 return git_revision 1058 return git_revision
1057 except (IndexError, ValueError): 1059 except (IndexError, ValueError):
1058 pass 1060 pass
1059 1061
1060 if not git_revision: 1062 if not git_revision:
1061 # Wasn't successful, try the old way of looking for "Prepare push to" 1063 # Wasn't successful, try the old way of looking for "Prepare push to"
1062 git_revision = source_control.ResolveToRevision( 1064 git_revision = self.source_control.ResolveToRevision(
1063 int(commit_position) - 1, 'v8_bleeding_edge', DEPOT_DEPS_NAME, -1, 1065 int(commit_position) - 1, 'v8_bleeding_edge', DEPOT_DEPS_NAME, -1,
1064 cwd=v8_bleeding_edge_dir) 1066 cwd=v8_bleeding_edge_dir)
1065 1067
1066 if git_revision: 1068 if git_revision:
1067 revision_info = source_control.QueryRevisionInfo(git_revision, 1069 revision_info = self.source_control.QueryRevisionInfo(git_revision,
1068 cwd=v8_bleeding_edge_dir) 1070 cwd=v8_bleeding_edge_dir)
1069 1071
1070 if 'Prepare push to trunk' in revision_info['subject']: 1072 if 'Prepare push to trunk' in revision_info['subject']:
1071 return git_revision 1073 return git_revision
1072 return None 1074 return None
1073 1075
1074 def _GetNearestV8BleedingEdgeFromTrunk(self, revision, search_forward=True): 1076 def _GetNearestV8BleedingEdgeFromTrunk(self, revision, search_forward=True):
1075 cwd = self.depot_registry.GetDepotDir('v8') 1077 cwd = self.depot_registry.GetDepotDir('v8')
1076 cmd = ['log', '--format=%ct', '-1', revision] 1078 cmd = ['log', '--format=%ct', '-1', revision]
1077 output = bisect_utils.CheckRunGit(cmd, cwd=cwd) 1079 output = bisect_utils.CheckRunGit(cmd, cwd=cwd)
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 1270
1269 Returns: 1271 Returns:
1270 Downloaded archive file path if exists, otherwise None. 1272 Downloaded archive file path if exists, otherwise None.
1271 """ 1273 """
1272 # Source archive file path on cloud storage using Git revision. 1274 # Source archive file path on cloud storage using Git revision.
1273 source_file = GetRemoteBuildPath( 1275 source_file = GetRemoteBuildPath(
1274 revision, self.opts.target_platform, target_arch, patch_sha) 1276 revision, self.opts.target_platform, target_arch, patch_sha)
1275 downloaded_archive = FetchFromCloudStorage(gs_bucket, source_file, out_dir) 1277 downloaded_archive = FetchFromCloudStorage(gs_bucket, source_file, out_dir)
1276 if not downloaded_archive: 1278 if not downloaded_archive:
1277 # Get commit position for the given SHA. 1279 # Get commit position for the given SHA.
1278 commit_position = source_control.GetCommitPosition(revision) 1280 commit_position = self.source_control.GetCommitPosition(revision)
1279 if commit_position: 1281 if commit_position:
1280 # Source archive file path on cloud storage using SVN revision. 1282 # Source archive file path on cloud storage using SVN revision.
1281 source_file = GetRemoteBuildPath( 1283 source_file = GetRemoteBuildPath(
1282 commit_position, self.opts.target_platform, target_arch, patch_sha) 1284 commit_position, self.opts.target_platform, target_arch, patch_sha)
1283 return FetchFromCloudStorage(gs_bucket, source_file, out_dir) 1285 return FetchFromCloudStorage(gs_bucket, source_file, out_dir)
1284 return downloaded_archive 1286 return downloaded_archive
1285 1287
1286 def DownloadCurrentBuild(self, revision, depot, build_type='Release'): 1288 def DownloadCurrentBuild(self, revision, depot, build_type='Release'):
1287 """Downloads the build archive for the given revision. 1289 """Downloads the build archive for the given revision.
1288 1290
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform) 1398 raise NotImplementedError('Unsupported Platform "%s".' % sys.platform)
1397 if not fetch_build: 1399 if not fetch_build:
1398 return False 1400 return False
1399 1401
1400 # Create a unique ID for each build request posted to try server builders. 1402 # Create a unique ID for each build request posted to try server builders.
1401 # This ID is added to "Reason" property of the build. 1403 # This ID is added to "Reason" property of the build.
1402 build_request_id = GetSHA1HexDigest( 1404 build_request_id = GetSHA1HexDigest(
1403 '%s-%s-%s' % (git_revision, patch, time.time())) 1405 '%s-%s-%s' % (git_revision, patch, time.time()))
1404 1406
1405 # Reverts any changes to DEPS file. 1407 # Reverts any changes to DEPS file.
1406 source_control.CheckoutFileAtRevision( 1408 self.source_control.CheckoutFileAtRevision(
1407 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd) 1409 bisect_utils.FILE_DEPS, git_revision, cwd=self.src_cwd)
1408 1410
1409 bot_name, build_timeout = GetBuilderNameAndBuildTime( 1411 bot_name, build_timeout = GetBuilderNameAndBuildTime(
1410 self.opts.target_platform, self.opts.target_arch) 1412 self.opts.target_platform, self.opts.target_arch)
1411 target_file = None 1413 target_file = None
1412 try: 1414 try:
1413 # Execute try job request to build revision with patch. 1415 # Execute try job request to build revision with patch.
1414 _BuilderTryjob(git_revision, bot_name, build_request_id, patch) 1416 _BuilderTryjob(git_revision, bot_name, build_request_id, patch)
1415 target_file, error_msg = _WaitUntilBuildIsReady( 1417 target_file, error_msg = _WaitUntilBuildIsReady(
1416 fetch_build, bot_name, self.opts.builder_host, 1418 fetch_build, bot_name, self.opts.builder_host,
(...skipping 26 matching lines...) Expand all
1443 1445
1444 Returns: 1446 Returns:
1445 Updated DEPS content as string if deps key is found, otherwise None. 1447 Updated DEPS content as string if deps key is found, otherwise None.
1446 """ 1448 """
1447 # Check whether the depot and revision pattern in DEPS file vars 1449 # Check whether the depot and revision pattern in DEPS file vars
1448 # e.g. for webkit the format is "webkit_revision": "12345". 1450 # e.g. for webkit the format is "webkit_revision": "12345".
1449 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key, 1451 deps_revision = re.compile(r'(?<="%s": ")([0-9]+)(?=")' % deps_key,
1450 re.MULTILINE) 1452 re.MULTILINE)
1451 new_data = None 1453 new_data = None
1452 if re.search(deps_revision, deps_contents): 1454 if re.search(deps_revision, deps_contents):
1453 commit_position = source_control.GetCommitPosition( 1455 commit_position = self.source_control.GetCommitPosition(
1454 git_revision, self.depot_registry.GetDepotDir(depot)) 1456 git_revision, self.depot_registry.GetDepotDir(depot))
1455 if not commit_position: 1457 if not commit_position:
1456 print 'Could not determine commit position for %s' % git_revision 1458 print 'Could not determine commit position for %s' % git_revision
1457 return None 1459 return None
1458 # Update the revision information for the given depot 1460 # Update the revision information for the given depot
1459 new_data = re.sub(deps_revision, str(commit_position), deps_contents) 1461 new_data = re.sub(deps_revision, str(commit_position), deps_contents)
1460 else: 1462 else:
1461 # Check whether the depot and revision pattern in DEPS file vars 1463 # Check whether the depot and revision pattern in DEPS file vars
1462 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..". 1464 # e.g. for webkit the format is "webkit_revision": "559a6d4ab7a84c539..".
1463 deps_revision = re.compile( 1465 deps_revision = re.compile(
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path) 1536 raise RuntimeError('DEPS file does not exists.[%s]' % deps_file_path)
1535 # Get current chromium revision (git hash). 1537 # Get current chromium revision (git hash).
1536 cmd = ['rev-parse', 'HEAD'] 1538 cmd = ['rev-parse', 'HEAD']
1537 chromium_sha = bisect_utils.CheckRunGit(cmd).strip() 1539 chromium_sha = bisect_utils.CheckRunGit(cmd).strip()
1538 if not chromium_sha: 1540 if not chromium_sha:
1539 raise RuntimeError('Failed to determine Chromium revision for %s' % 1541 raise RuntimeError('Failed to determine Chromium revision for %s' %
1540 revision) 1542 revision)
1541 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or 1543 if ('chromium' in DEPOT_DEPS_NAME[depot]['from'] or
1542 'v8' in DEPOT_DEPS_NAME[depot]['from']): 1544 'v8' in DEPOT_DEPS_NAME[depot]['from']):
1543 # Checkout DEPS file for the current chromium revision. 1545 # Checkout DEPS file for the current chromium revision.
1544 if source_control.CheckoutFileAtRevision( 1546 if self.source_control.CheckoutFileAtRevision(
1545 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd): 1547 bisect_utils.FILE_DEPS, chromium_sha, cwd=self.src_cwd):
1546 if self.UpdateDeps(revision, depot, deps_file_path): 1548 if self.UpdateDeps(revision, depot, deps_file_path):
1547 diff_command = [ 1549 diff_command = [
1548 'diff', 1550 'diff',
1549 '--src-prefix=', 1551 '--src-prefix=',
1550 '--dst-prefix=', 1552 '--dst-prefix=',
1551 '--no-ext-diff', 1553 '--no-ext-diff',
1552 bisect_utils.FILE_DEPS, 1554 bisect_utils.FILE_DEPS,
1553 ] 1555 ]
1554 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd) 1556 diff_text = bisect_utils.CheckRunGit(diff_command, cwd=self.src_cwd)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 Then until crrev.com/276628 *both* (android-chromium-testshell and 1611 Then until crrev.com/276628 *both* (android-chromium-testshell and
1610 android-chrome-shell) work. After that rev 276628 *only* 1612 android-chrome-shell) work. After that rev 276628 *only*
1611 android-chrome-shell works. The bisect_perf_regression.py script should 1613 android-chrome-shell works. The bisect_perf_regression.py script should
1612 handle these cases and set appropriate browser type based on revision. 1614 handle these cases and set appropriate browser type based on revision.
1613 """ 1615 """
1614 if self.opts.target_platform in ['android']: 1616 if self.opts.target_platform in ['android']:
1615 # When its a third_party depot, get the chromium revision. 1617 # When its a third_party depot, get the chromium revision.
1616 if depot != 'chromium': 1618 if depot != 'chromium':
1617 revision = bisect_utils.CheckRunGit( 1619 revision = bisect_utils.CheckRunGit(
1618 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip() 1620 ['rev-parse', 'HEAD'], cwd=self.src_cwd).strip()
1619 commit_position = source_control.GetCommitPosition(revision, 1621 commit_position = self.source_control.GetCommitPosition(revision,
1620 cwd=self.src_cwd) 1622 cwd=self.src_cwd)
1621 if not commit_position: 1623 if not commit_position:
1622 return command_to_run 1624 return command_to_run
1623 cmd_re = re.compile('--browser=(?P<browser_type>\S+)') 1625 cmd_re = re.compile('--browser=(?P<browser_type>\S+)')
1624 matches = cmd_re.search(command_to_run) 1626 matches = cmd_re.search(command_to_run)
1625 if bisect_utils.IsStringInt(commit_position) and matches: 1627 if bisect_utils.IsStringInt(commit_position) and matches:
1626 cmd_browser = matches.group('browser_type') 1628 cmd_browser = matches.group('browser_type')
1627 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell': 1629 if commit_position <= 274857 and cmd_browser == 'android-chrome-shell':
1628 return command_to_run.replace(cmd_browser, 1630 return command_to_run.replace(cmd_browser,
1629 'android-chromium-testshell') 1631 'android-chromium-testshell')
1630 elif (commit_position >= 276628 and 1632 elif (commit_position >= 276628 and
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 """ 1796 """
1795 revisions_to_sync = [[depot, revision]] 1797 revisions_to_sync = [[depot, revision]]
1796 1798
1797 is_base = ((depot == 'chromium') or (depot == 'cros') or 1799 is_base = ((depot == 'chromium') or (depot == 'cros') or
1798 (depot == 'android-chrome')) 1800 (depot == 'android-chrome'))
1799 1801
1800 # Some SVN depots were split into multiple git depots, so we need to 1802 # Some SVN depots were split into multiple git depots, so we need to
1801 # figure out for each mirror which git revision to grab. There's no 1803 # figure out for each mirror which git revision to grab. There's no
1802 # guarantee that the SVN revision will exist for each of the dependent 1804 # guarantee that the SVN revision will exist for each of the dependent
1803 # depots, so we have to grep the git logs and grab the next earlier one. 1805 # depots, so we have to grep the git logs and grab the next earlier one.
1804 if not is_base and DEPOT_DEPS_NAME[depot]['depends']: 1806 if (not is_base
1805 commit_position = source_control.GetCommitPosition(revision) 1807 and DEPOT_DEPS_NAME[depot]['depends']
1808 and self.source_control.IsGit()):
1809 commit_position = self.source_control.GetCommitPosition(revision)
1806 1810
1807 for d in DEPOT_DEPS_NAME[depot]['depends']: 1811 for d in DEPOT_DEPS_NAME[depot]['depends']:
1808 self.depot_registry.ChangeToDepotDir(d) 1812 self.depot_registry.ChangeToDepotDir(d)
1809 1813
1810 dependant_rev = source_control.ResolveToRevision( 1814 dependant_rev = self.source_control.ResolveToRevision(
1811 commit_position, d, DEPOT_DEPS_NAME, -1000) 1815 commit_position, d, DEPOT_DEPS_NAME, -1000)
1812 1816
1813 if dependant_rev: 1817 if dependant_rev:
1814 revisions_to_sync.append([d, dependant_rev]) 1818 revisions_to_sync.append([d, dependant_rev])
1815 1819
1816 num_resolved = len(revisions_to_sync) 1820 num_resolved = len(revisions_to_sync)
1817 num_needed = len(DEPOT_DEPS_NAME[depot]['depends']) 1821 num_needed = len(DEPOT_DEPS_NAME[depot]['depends'])
1818 1822
1819 self.depot_registry.ChangeToDepotDir(depot) 1823 self.depot_registry.ChangeToDepotDir(depot)
1820 1824
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 if not builder.SetupAndroidBuildEnvironment(self.opts, 1891 if not builder.SetupAndroidBuildEnvironment(self.opts,
1888 path_to_src=self.src_cwd): 1892 path_to_src=self.src_cwd):
1889 return False 1893 return False
1890 1894
1891 if depot == 'cros': 1895 if depot == 'cros':
1892 return self.CreateCrosChroot() 1896 return self.CreateCrosChroot()
1893 else: 1897 else:
1894 return self.RunGClientHooks() 1898 return self.RunGClientHooks()
1895 return True 1899 return True
1896 1900
1897 @staticmethod 1901 def ShouldSkipRevision(self, depot, revision):
1898 def ShouldSkipRevision(depot, revision):
1899 """Checks whether a particular revision can be safely skipped. 1902 """Checks whether a particular revision can be safely skipped.
1900 1903
1901 Some commits can be safely skipped (such as a DEPS roll), since the tool 1904 Some commits can be safely skipped (such as a DEPS roll), since the tool
1902 is git based those changes would have no effect. 1905 is git based those changes would have no effect.
1903 1906
1904 Args: 1907 Args:
1905 depot: The depot being bisected. 1908 depot: The depot being bisected.
1906 revision: Current revision we're synced to. 1909 revision: Current revision we're synced to.
1907 1910
1908 Returns: 1911 Returns:
1909 True if we should skip building/testing this revision. 1912 True if we should skip building/testing this revision.
1910 """ 1913 """
1911 if depot == 'chromium': 1914 if depot == 'chromium':
1912 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] 1915 if self.source_control.IsGit():
1913 output = bisect_utils.CheckRunGit(cmd) 1916 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision]
1917 output = bisect_utils.CheckRunGit(cmd)
1914 1918
1915 files = output.splitlines() 1919 files = output.splitlines()
1916 1920
1917 if len(files) == 1 and files[0] == 'DEPS': 1921 if len(files) == 1 and files[0] == 'DEPS':
1918 return True 1922 return True
1919 1923
1920 return False 1924 return False
1921 1925
1922 def RunTest(self, revision, depot, command, metric, skippable=False): 1926 def RunTest(self, revision, depot, command, metric, skippable=False):
1923 """Performs a full sync/build/run of the specified revision. 1927 """Performs a full sync/build/run of the specified revision.
1924 1928
1925 Args: 1929 Args:
1926 revision: The revision to sync to. 1930 revision: The revision to sync to.
1927 depot: The depot that's being used at the moment (src, webkit, etc.) 1931 depot: The depot that's being used at the moment (src, webkit, etc.)
1928 command: The command to execute the performance test. 1932 command: The command to execute the performance test.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 2015
2012 if sync_client: 2016 if sync_client:
2013 self.PerformPreBuildCleanup() 2017 self.PerformPreBuildCleanup()
2014 2018
2015 # When using gclient to sync, you need to specify the depot you 2019 # When using gclient to sync, you need to specify the depot you
2016 # want so that all the dependencies sync properly as well. 2020 # want so that all the dependencies sync properly as well.
2017 # i.e. gclient sync src@<SHA1> 2021 # i.e. gclient sync src@<SHA1>
2018 if sync_client == 'gclient': 2022 if sync_client == 'gclient':
2019 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) 2023 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision)
2020 2024
2021 sync_success = source_control.SyncToRevision(revision, sync_client) 2025 sync_success = self.source_control.SyncToRevision(revision, sync_client)
2022 if not sync_success: 2026 if not sync_success:
2023 return False 2027 return False
2024 2028
2025 return True 2029 return True
2026 2030
2027 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): 2031 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value):
2028 """Given known good and bad values, decide if the current_value passed 2032 """Given known good and bad values, decide if the current_value passed
2029 or failed. 2033 or failed.
2030 2034
2031 Args: 2035 Args:
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 good_svn_revision: Last known good svn revision. 2213 good_svn_revision: Last known good svn revision.
2210 2214
2211 Returns: 2215 Returns:
2212 A tuple with the new bad and good revisions. 2216 A tuple with the new bad and good revisions.
2213 """ 2217 """
2214 # DONOT perform nudge because at revision 291563 .DEPS.git was removed 2218 # DONOT perform nudge because at revision 291563 .DEPS.git was removed
2215 # and source contain only DEPS file for dependency changes. 2219 # and source contain only DEPS file for dependency changes.
2216 if good_svn_revision >= 291563: 2220 if good_svn_revision >= 291563:
2217 return (bad_revision, good_revision) 2221 return (bad_revision, good_revision)
2218 2222
2219 if self.opts.target_platform == 'chromium': 2223 if self.source_control.IsGit() and self.opts.target_platform == 'chromium':
2220 changes_to_deps = source_control.QueryFileRevisionHistory( 2224 changes_to_deps = self.source_control.QueryFileRevisionHistory(
2221 bisect_utils.FILE_DEPS, good_revision, bad_revision) 2225 bisect_utils.FILE_DEPS, good_revision, bad_revision)
2222 2226
2223 if changes_to_deps: 2227 if changes_to_deps:
2224 # DEPS file was changed, search from the oldest change to DEPS file to 2228 # DEPS file was changed, search from the oldest change to DEPS file to
2225 # bad_revision to see if there are matching .DEPS.git changes. 2229 # bad_revision to see if there are matching .DEPS.git changes.
2226 oldest_deps_change = changes_to_deps[-1] 2230 oldest_deps_change = changes_to_deps[-1]
2227 changes_to_gitdeps = source_control.QueryFileRevisionHistory( 2231 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory(
2228 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) 2232 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision)
2229 2233
2230 if len(changes_to_deps) != len(changes_to_gitdeps): 2234 if len(changes_to_deps) != len(changes_to_gitdeps):
2231 # Grab the timestamp of the last DEPS change 2235 # Grab the timestamp of the last DEPS change
2232 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] 2236 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]]
2233 output = bisect_utils.CheckRunGit(cmd) 2237 output = bisect_utils.CheckRunGit(cmd)
2234 commit_time = int(output) 2238 commit_time = int(output)
2235 2239
2236 # Try looking for a commit that touches the .DEPS.git file in the 2240 # Try looking for a commit that touches the .DEPS.git file in the
2237 # next 15 minutes after the DEPS file change. 2241 # next 15 minutes after the DEPS file change.
(...skipping 15 matching lines...) Expand all
2253 self, target_depot, good_revision, bad_revision): 2257 self, target_depot, good_revision, bad_revision):
2254 """Checks that |good_revision| is an earlier revision than |bad_revision|. 2258 """Checks that |good_revision| is an earlier revision than |bad_revision|.
2255 2259
2256 Args: 2260 Args:
2257 good_revision: Number/tag of the known good revision. 2261 good_revision: Number/tag of the known good revision.
2258 bad_revision: Number/tag of the known bad revision. 2262 bad_revision: Number/tag of the known bad revision.
2259 2263
2260 Returns: 2264 Returns:
2261 True if the revisions are in the proper order (good earlier than bad). 2265 True if the revisions are in the proper order (good earlier than bad).
2262 """ 2266 """
2263 if target_depot != 'cros': 2267 if self.source_control.IsGit() and target_depot != 'cros':
2264 cwd = self.depot_registry.GetDepotDir(target_depot) 2268 cwd = self.depot_registry.GetDepotDir(target_depot)
2265 good_position = source_control.GetCommitPosition(good_revision, cwd) 2269 good_position = self.source_control.GetCommitPosition(good_revision, cwd)
2266 bad_position = source_control.GetCommitPosition(bad_revision, cwd) 2270 bad_position = self.source_control.GetCommitPosition(bad_revision, cwd)
2267 else: 2271 else:
2268 # CrOS and SVN use integers. 2272 # CrOS and SVN use integers.
2269 good_position = int(good_revision) 2273 good_position = int(good_revision)
2270 bad_position = int(bad_revision) 2274 bad_position = int(bad_revision)
2271 2275
2272 return good_position <= bad_position 2276 return good_position <= bad_position
2273 2277
2274 def CanPerformBisect(self, good_revision, bad_revision): 2278 def CanPerformBisect(self, good_revision, bad_revision):
2275 """Checks whether a given revision is bisectable. 2279 """Checks whether a given revision is bisectable.
2276 2280
2277 Checks for following: 2281 Checks for following:
2278 1. Non-bisectable revsions for android bots (refer to crbug.com/385324). 2282 1. Non-bisectable revsions for android bots (refer to crbug.com/385324).
2279 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274). 2283 2. Non-bisectable revsions for Windows bots (refer to crbug.com/405274).
2280 2284
2281 Args: 2285 Args:
2282 good_revision: Known good revision. 2286 good_revision: Known good revision.
2283 bad_revision: Known bad revision. 2287 bad_revision: Known bad revision.
2284 2288
2285 Returns: 2289 Returns:
2286 A dictionary indicating the result. If revision is not bisectable, 2290 A dictionary indicating the result. If revision is not bisectable,
2287 this will contain the field "error", otherwise None. 2291 this will contain the field "error", otherwise None.
2288 """ 2292 """
2289 if self.opts.target_platform == 'android': 2293 if self.opts.target_platform == 'android':
2290 good_revision = source_control.GetCommitPosition(good_revision) 2294 good_revision = self.source_control.GetCommitPosition(good_revision)
2291 if (bisect_utils.IsStringInt(good_revision) 2295 if (bisect_utils.IsStringInt(good_revision)
2292 and good_revision < 265549): 2296 and good_revision < 265549):
2293 return {'error': ( 2297 return {'error': (
2294 'Bisect cannot continue for the given revision range.\n' 2298 'Bisect cannot continue for the given revision range.\n'
2295 'It is impossible to bisect Android regressions ' 2299 'It is impossible to bisect Android regressions '
2296 'prior to r265549, which allows the bisect bot to ' 2300 'prior to r265549, which allows the bisect bot to '
2297 'rely on Telemetry to do apk installation of the most recently ' 2301 'rely on Telemetry to do apk installation of the most recently '
2298 'built local ChromeShell(refer to crbug.com/385324).\n' 2302 'built local ChromeShell(refer to crbug.com/385324).\n'
2299 'Please try bisecting revisions greater than or equal to r265549.')} 2303 'Please try bisecting revisions greater than or equal to r265549.')}
2300 2304
2301 if bisect_utils.IsWindowsHost(): 2305 if bisect_utils.IsWindowsHost():
2302 good_revision = source_control.GetCommitPosition(good_revision) 2306 good_revision = self.source_control.GetCommitPosition(good_revision)
2303 bad_revision = source_control.GetCommitPosition(bad_revision) 2307 bad_revision = self.source_control.GetCommitPosition(bad_revision)
2304 if (bisect_utils.IsStringInt(good_revision) and 2308 if (bisect_utils.IsStringInt(good_revision) and
2305 bisect_utils.IsStringInt(bad_revision)): 2309 bisect_utils.IsStringInt(bad_revision)):
2306 if (289987 <= good_revision < 290716 or 2310 if (289987 <= good_revision < 290716 or
2307 289987 <= bad_revision < 290716): 2311 289987 <= bad_revision < 290716):
2308 return {'error': ('Oops! Revision between r289987 and r290716 are ' 2312 return {'error': ('Oops! Revision between r289987 and r290716 are '
2309 'marked as dead zone for Windows due to ' 2313 'marked as dead zone for Windows due to '
2310 'crbug.com/405274. Please try another range.')} 2314 'crbug.com/405274. Please try another range.')}
2311 2315
2312 return None 2316 return None
2313 2317
2314 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): 2318 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric):
2315 """Given known good and bad revisions, run a binary search on all 2319 """Given known good and bad revisions, run a binary search on all
2316 intermediate revisions to determine the CL where the performance regression 2320 intermediate revisions to determine the CL where the performance regression
2317 occurred. 2321 occurred.
2318 2322
2319 Args: 2323 Args:
2320 command_to_run: Specify the command to execute the performance test. 2324 command_to_run: Specify the command to execute the performance test.
2321 good_revision: Number/tag of the known good revision. 2325 good_revision: Number/tag of the known good revision.
2322 bad_revision: Number/tag of the known bad revision. 2326 bad_revision: Number/tag of the known bad revision.
2323 metric: The performance metric to monitor. 2327 metric: The performance metric to monitor.
2324 2328
2325 Returns: 2329 Returns:
2326 A BisectResults object. 2330 A BisectResults object.
2327 """ 2331 """
2328 results = BisectResults(self.depot_registry) 2332 results = BisectResults(self.depot_registry, self.source_control)
2329 2333
2330 # Choose depot to bisect first 2334 # Choose depot to bisect first
2331 target_depot = 'chromium' 2335 target_depot = 'chromium'
2332 if self.opts.target_platform == 'cros': 2336 if self.opts.target_platform == 'cros':
2333 target_depot = 'cros' 2337 target_depot = 'cros'
2334 elif self.opts.target_platform == 'android-chrome': 2338 elif self.opts.target_platform == 'android-chrome':
2335 target_depot = 'android-chrome' 2339 target_depot = 'android-chrome'
2336 2340
2337 cwd = os.getcwd() 2341 cwd = os.getcwd()
2338 self.depot_registry.ChangeToDepotDir(target_depot) 2342 self.depot_registry.ChangeToDepotDir(target_depot)
2339 2343
2340 # If they passed SVN revisions, we can try match them to git SHA1 hashes. 2344 # If they passed SVN revisions, we can try match them to git SHA1 hashes.
2341 bad_revision = source_control.ResolveToRevision( 2345 bad_revision = self.source_control.ResolveToRevision(
2342 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) 2346 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100)
2343 good_revision = source_control.ResolveToRevision( 2347 good_revision = self.source_control.ResolveToRevision(
2344 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) 2348 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100)
2345 2349
2346 os.chdir(cwd) 2350 os.chdir(cwd)
2347 if bad_revision is None: 2351 if bad_revision is None:
2348 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in 2352 results.error = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in
2349 return results 2353 return results
2350 2354
2351 if good_revision is None: 2355 if good_revision is None:
2352 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in 2356 results.error = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in
2353 return results 2357 return results
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
2599 level = 'high' 2603 level = 'high'
2600 else: 2604 else:
2601 level = 'low' 2605 level = 'low'
2602 warning = ' and warnings' 2606 warning = ' and warnings'
2603 if not self.warnings: 2607 if not self.warnings:
2604 warning = '' 2608 warning = ''
2605 return confidence_status % {'level': level, 'warning': warning} 2609 return confidence_status % {'level': level, 'warning': warning}
2606 2610
2607 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot): 2611 def _GetViewVCLinkFromDepotAndHash(self, revision_id, depot):
2608 """Gets link to the repository browser.""" 2612 """Gets link to the repository browser."""
2609 info = source_control.QueryRevisionInfo(revision_id, 2613 info = self.source_control.QueryRevisionInfo(revision_id,
2610 self.depot_registry.GetDepotDir(depot)) 2614 self.depot_registry.GetDepotDir(depot))
2611 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'): 2615 if depot and DEPOT_DEPS_NAME[depot].has_key('viewvc'):
2612 try: 2616 try:
2613 # Format is "git-svn-id: svn://....@123456 <other data>" 2617 # Format is "git-svn-id: svn://....@123456 <other data>"
2614 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i] 2618 svn_line = [i for i in info['body'].splitlines() if 'git-svn-id:' in i]
2615 svn_revision = svn_line[0].split('@') 2619 svn_revision = svn_line[0].split('@')
2616 svn_revision = svn_revision[1].split(' ')[0] 2620 svn_revision = svn_revision[1].split(' ')[0]
2617 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision 2621 return DEPOT_DEPS_NAME[depot]['viewvc'] + svn_revision
2618 except IndexError: 2622 except IndexError:
2619 return '' 2623 return ''
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 2712
2709 # If confidence is too low, don't bother outputting good/bad. 2713 # If confidence is too low, don't bother outputting good/bad.
2710 if not confidence: 2714 if not confidence:
2711 state_str = '' 2715 state_str = ''
2712 state_str = state_str.center(13, ' ') 2716 state_str = state_str.center(13, ' ')
2713 2717
2714 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id, 2718 cl_link = self._GetViewVCLinkFromDepotAndHash(current_id,
2715 current_data['depot']) 2719 current_data['depot'])
2716 if not cl_link: 2720 if not cl_link:
2717 cl_link = current_id 2721 cl_link = current_id
2718 commit_position = source_control.GetCommitPosition( 2722 commit_position = self.source_control.GetCommitPosition(
2719 current_id, self.depot_registry.GetDepotDir(current_data['depot'])) 2723 current_id, self.depot_registry.GetDepotDir(current_data['depot']))
2720 commit_position = str(commit_position) 2724 commit_position = str(commit_position)
2721 if not commit_position: 2725 if not commit_position:
2722 commit_position = '' 2726 commit_position = ''
2723 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link, 2727 self._PrintTestedCommitsEntry(current_data, commit_position, cl_link,
2724 state_str) 2728 state_str)
2725 2729
2726 def _PrintReproSteps(self): 2730 def _PrintReproSteps(self):
2727 """Prints out a section of the results explaining how to run the test. 2731 """Prints out a section of the results explaining how to run the test.
2728 2732
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
3212 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps) 3216 bisect_utils.CreateBisectDirectoryAndSetupDepot(opts, custom_deps)
3213 3217
3214 os.chdir(os.path.join(os.getcwd(), 'src')) 3218 os.chdir(os.path.join(os.getcwd(), 'src'))
3215 3219
3216 if not RemoveBuildFiles(opts.target_build_type): 3220 if not RemoveBuildFiles(opts.target_build_type):
3217 raise RuntimeError('Something went wrong removing the build files.') 3221 raise RuntimeError('Something went wrong removing the build files.')
3218 3222
3219 if not _IsPlatformSupported(): 3223 if not _IsPlatformSupported():
3220 raise RuntimeError('Sorry, this platform isn\'t supported yet.') 3224 raise RuntimeError('Sorry, this platform isn\'t supported yet.')
3221 3225
3222 if not source_control.IsInGitRepository(): 3226 # Check what source control method is being used, and create a
3227 # SourceControl object if possible.
3228 source_control = source_control_module.DetermineAndCreateSourceControl(opts)
3229
3230 if not source_control:
3223 raise RuntimeError( 3231 raise RuntimeError(
3224 'Sorry, only the git workflow is supported at the moment.') 3232 'Sorry, only the git workflow is supported at the moment.')
3225 3233
3226 # gClient sync seems to fail if you're not in master branch. 3234 # gClient sync seems to fail if you're not in master branch.
3227 if (not source_control.IsInProperBranch() and 3235 if (not source_control.IsInProperBranch() and
3228 not opts.debug_ignore_sync and 3236 not opts.debug_ignore_sync and
3229 not opts.working_directory): 3237 not opts.working_directory):
3230 raise RuntimeError('You must switch to master branch to run bisection.') 3238 raise RuntimeError('You must switch to master branch to run bisection.')
3231 bisect_test = BisectPerformanceMetrics(opts) 3239 bisect_test = BisectPerformanceMetrics(source_control, opts)
3232 try: 3240 try:
3233 bisect_results = bisect_test.Run(opts.command, 3241 bisect_results = bisect_test.Run(opts.command,
3234 opts.bad_revision, 3242 opts.bad_revision,
3235 opts.good_revision, 3243 opts.good_revision,
3236 opts.metric) 3244 opts.metric)
3237 if bisect_results.error: 3245 if bisect_results.error:
3238 raise RuntimeError(bisect_results.error) 3246 raise RuntimeError(bisect_results.error)
3239 bisect_test.FormatAndPrintResults(bisect_results) 3247 bisect_test.FormatAndPrintResults(bisect_results)
3240 return 0 3248 return 0
3241 finally: 3249 finally:
3242 bisect_test.PerformCleanup() 3250 bisect_test.PerformCleanup()
3243 except RuntimeError, e: 3251 except RuntimeError, e:
3244 if opts.output_buildbot_annotations: 3252 if opts.output_buildbot_annotations:
3245 # The perf dashboard scrapes the "results" step in order to comment on 3253 # The perf dashboard scrapes the "results" step in order to comment on
3246 # bugs. If you change this, please update the perf dashboard as well. 3254 # bugs. If you change this, please update the perf dashboard as well.
3247 bisect_utils.OutputAnnotationStepStart('Results') 3255 bisect_utils.OutputAnnotationStepStart('Results')
3248 print 'Error: %s' % e.message 3256 print 'Error: %s' % e.message
3249 if opts.output_buildbot_annotations: 3257 if opts.output_buildbot_annotations:
3250 bisect_utils.OutputAnnotationStepClosed() 3258 bisect_utils.OutputAnnotationStepClosed()
3251 return 1 3259 return 1
3252 3260
3253 3261
3254 if __name__ == '__main__': 3262 if __name__ == '__main__':
3255 sys.exit(main()) 3263 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/auto_bisect/bisect_perf_regression_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698