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

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

Issue 503283002: Update bisect script to handle deleted .DEPS.git from chromium source (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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/auto_bisect/source_control.py ('k') | 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 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 depot: Name of depot being bisected. 1060 depot: Name of depot being bisected.
1061 1061
1062 Returns: 1062 Returns:
1063 A dict in the format {depot:revision} if successful, otherwise None. 1063 A dict in the format {depot:revision} if successful, otherwise None.
1064 """ 1064 """
1065 try: 1065 try:
1066 deps_data = { 1066 deps_data = {
1067 'Var': lambda _: deps_data["vars"][_], 1067 'Var': lambda _: deps_data["vars"][_],
1068 'From': lambda *args: None, 1068 'From': lambda *args: None,
1069 } 1069 }
1070 execfile(bisect_utils.FILE_DEPS_GIT, {}, deps_data) 1070
1071 deps_file = bisect_utils.FILE_DEPS_GIT
1072 if not os.path.exists(deps_file):
1073 deps_file = bisect_utils.FILE_DEPS
1074 execfile(deps_file, {}, deps_data)
1071 deps_data = deps_data['deps'] 1075 deps_data = deps_data['deps']
1072 1076
1073 rxp = re.compile(".git@(?P<revision>[a-fA-F0-9]+)") 1077 rxp = re.compile(".git@(?P<revision>[a-fA-F0-9]+)")
1074 results = {} 1078 results = {}
1075 for depot_name, depot_data in DEPOT_DEPS_NAME.iteritems(): 1079 for depot_name, depot_data in DEPOT_DEPS_NAME.iteritems():
1076 if (depot_data.get('platform') and 1080 if (depot_data.get('platform') and
1077 depot_data.get('platform') != os.name): 1081 depot_data.get('platform') != os.name):
1078 continue 1082 continue
1079 1083
1080 if (depot_data.get('recurse') and depot in depot_data.get('from')): 1084 if (depot_data.get('recurse') and depot in depot_data.get('from')):
1081 depot_data_src = depot_data.get('src') or depot_data.get('src_old') 1085 depot_data_src = depot_data.get('src') or depot_data.get('src_old')
1082 src_dir = deps_data.get(depot_data_src) 1086 src_dir = deps_data.get(depot_data_src)
1083 if src_dir: 1087 if src_dir:
1084 self.depot_cwd[depot_name] = os.path.join(self.src_cwd, 1088 self.depot_cwd[depot_name] = os.path.join(self.src_cwd,
1085 depot_data_src[4:]) 1089 depot_data_src[4:])
1086 re_results = rxp.search(src_dir) 1090 re_results = rxp.search(src_dir)
1087 if re_results: 1091 if re_results:
1088 results[depot_name] = re_results.group('revision') 1092 results[depot_name] = re_results.group('revision')
1089 else: 1093 else:
1090 warning_text = ('Could not parse revision for %s while bisecting ' 1094 warning_text = ('Could not parse revision for %s while bisecting '
1091 '%s' % (depot_name, depot)) 1095 '%s' % (depot_name, depot))
1092 if not warning_text in self.warnings: 1096 if not warning_text in self.warnings:
1093 self.warnings.append(warning_text) 1097 self.warnings.append(warning_text)
1094 else: 1098 else:
1095 results[depot_name] = None 1099 results[depot_name] = None
1096 return results 1100 return results
1097 except ImportError: 1101 except ImportError:
1098 deps_file_contents = ReadStringFromFile(bisect_utils.FILE_DEPS_GIT) 1102 deps_file_contents = ReadStringFromFile(deps_file)
1099 parse_results = _ParseRevisionsFromDEPSFileManually(deps_file_contents) 1103 parse_results = _ParseRevisionsFromDEPSFileManually(deps_file_contents)
1100 results = {} 1104 results = {}
1101 for depot_name, depot_revision in parse_results.iteritems(): 1105 for depot_name, depot_revision in parse_results.iteritems():
1102 depot_revision = depot_revision.strip('@') 1106 depot_revision = depot_revision.strip('@')
1103 print depot_name, depot_revision 1107 print depot_name, depot_revision
1104 for current_name, current_data in DEPOT_DEPS_NAME.iteritems(): 1108 for current_name, current_data in DEPOT_DEPS_NAME.iteritems():
1105 if (current_data.has_key('deps_var') and 1109 if (current_data.has_key('deps_var') and
1106 current_data['deps_var'] == depot_name): 1110 current_data['deps_var'] == depot_name):
1107 src_name = current_name 1111 src_name = current_name
1108 results[src_name] = depot_revision 1112 results[src_name] = depot_revision
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 def PerformWebkitDirectoryCleanup(self, revision): 1774 def PerformWebkitDirectoryCleanup(self, revision):
1771 """Cleans up the Webkit directory before syncing another revision. 1775 """Cleans up the Webkit directory before syncing another revision.
1772 1776
1773 If the script is switching between Blink and WebKit during bisect, 1777 If the script is switching between Blink and WebKit during bisect,
1774 its faster to just delete the directory rather than leave it up to git 1778 its faster to just delete the directory rather than leave it up to git
1775 to sync. 1779 to sync.
1776 1780
1777 Returns: 1781 Returns:
1778 True if successful. 1782 True if successful.
1779 """ 1783 """
1780 if not self.source_control.CheckoutFileAtRevision(
1781 bisect_utils.FILE_DEPS_GIT, revision, cwd=self.src_cwd):
1782 return False
1783
1784 cwd = os.getcwd() 1784 cwd = os.getcwd()
1785 os.chdir(self.src_cwd) 1785 os.chdir(self.src_cwd)
1786 1786
1787 is_blink = bisect_utils.IsDepsFileBlink() 1787 is_blink = bisect_utils.IsDepsFileBlink(revision)
1788 1788
1789 os.chdir(cwd) 1789 os.chdir(cwd)
1790 1790
1791 if not self.source_control.RevertFileToHead(
1792 bisect_utils.FILE_DEPS_GIT):
1793 return False
1794
1795 if self.was_blink != is_blink: 1791 if self.was_blink != is_blink:
1796 self.was_blink = is_blink 1792 self.was_blink = is_blink
1797 # Removes third_party/Webkit directory. 1793 # Removes third_party/Webkit directory.
1798 return bisect_utils.RemoveThirdPartyDirectory('Webkit') 1794 return bisect_utils.RemoveThirdPartyDirectory('Webkit')
1799 return True 1795 return True
1800 1796
1801 def PerformCrosChrootCleanup(self): 1797 def PerformCrosChrootCleanup(self):
1802 """Deletes the chroot. 1798 """Deletes the chroot.
1803 1799
1804 Returns: 1800 Returns:
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 2164
2169 print 2165 print
2170 print 'Revisions to bisect on [%s]:' % depot 2166 print 'Revisions to bisect on [%s]:' % depot
2171 for revision_id in revision_list: 2167 for revision_id in revision_list:
2172 print ' -> %s' % (revision_id, ) 2168 print ' -> %s' % (revision_id, )
2173 print 2169 print
2174 2170
2175 if self.opts.output_buildbot_annotations: 2171 if self.opts.output_buildbot_annotations:
2176 bisect_utils.OutputAnnotationStepClosed() 2172 bisect_utils.OutputAnnotationStepClosed()
2177 2173
2178 def NudgeRevisionsIfDEPSChange(self, bad_revision, good_revision): 2174 def NudgeRevisionsIfDEPSChange(self, bad_revision, good_revision,
2175 good_svn_revision=None):
2179 """Checks to see if changes to DEPS file occurred, and that the revision 2176 """Checks to see if changes to DEPS file occurred, and that the revision
2180 range also includes the change to .DEPS.git. If it doesn't, attempts to 2177 range also includes the change to .DEPS.git. If it doesn't, attempts to
2181 expand the revision range to include it. 2178 expand the revision range to include it.
2182 2179
2183 Args: 2180 Args:
2184 bad_rev: First known bad revision. 2181 bad_revision: First known bad git revision.
2185 good_revision: Last known good revision. 2182 good_revision: Last known good git revision.
2183 good_svn_revision: Last known good svn revision.
2186 2184
2187 Returns: 2185 Returns:
2188 A tuple with the new bad and good revisions. 2186 A tuple with the new bad and good revisions.
2189 """ 2187 """
2188 # DONOT perform nudge because at revision 291563 .DEPS.git was removed
2189 # and source contain only DEPS file for dependency changes.
2190 if good_svn_revision >= 291563:
2191 return (bad_revision, good_revision)
2192
2190 if self.source_control.IsGit() and self.opts.target_platform == 'chromium': 2193 if self.source_control.IsGit() and self.opts.target_platform == 'chromium':
2191 changes_to_deps = self.source_control.QueryFileRevisionHistory( 2194 changes_to_deps = self.source_control.QueryFileRevisionHistory(
2192 'DEPS', good_revision, bad_revision) 2195 'DEPS', good_revision, bad_revision)
2193 2196
2194 if changes_to_deps: 2197 if changes_to_deps:
2195 # DEPS file was changed, search from the oldest change to DEPS file to 2198 # DEPS file was changed, search from the oldest change to DEPS file to
2196 # bad_revision to see if there are matching .DEPS.git changes. 2199 # bad_revision to see if there are matching .DEPS.git changes.
2197 oldest_deps_change = changes_to_deps[-1] 2200 oldest_deps_change = changes_to_deps[-1]
2198 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory( 2201 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory(
2199 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) 2202 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision)
2200 2203
2201 if len(changes_to_deps) != len(changes_to_gitdeps): 2204 if len(changes_to_deps) != len(changes_to_gitdeps):
2202 # Grab the timestamp of the last DEPS change 2205 # Grab the timestamp of the last DEPS change
2203 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] 2206 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]]
2204 output = bisect_utils.CheckRunGit(cmd) 2207 output = bisect_utils.CheckRunGit(cmd)
2205 commit_time = int(output) 2208 commit_time = int(output)
2206 2209
2207 # Try looking for a commit that touches the .DEPS.git file in the 2210 # Try looking for a commit that touches the .DEPS.git file in the
2208 # next 15 minutes after the DEPS file change. 2211 # next 15 minutes after the DEPS file change.
2209 cmd = ['log', '--format=%H', '-1', 2212 cmd = ['log', '--format=%H', '-1',
2210 '--before=%d' % (commit_time + 900), '--after=%d' % commit_time, 2213 '--before=%d' % (commit_time + 900), '--after=%d' % commit_time,
2211 'origin/master', bisect_utils.FILE_DEPS_GIT] 2214 'origin/master', '--', bisect_utils.FILE_DEPS_GIT]
2212 output = bisect_utils.CheckRunGit(cmd) 2215 output = bisect_utils.CheckRunGit(cmd)
2213 output = output.strip() 2216 output = output.strip()
2214 if output: 2217 if output:
2215 self.warnings.append('Detected change to DEPS and modified ' 2218 self.warnings.append('Detected change to DEPS and modified '
2216 'revision range to include change to .DEPS.git') 2219 'revision range to include change to .DEPS.git')
2217 return (output, good_revision) 2220 return (output, good_revision)
2218 else: 2221 else:
2219 self.warnings.append('Detected change to DEPS but couldn\'t find ' 2222 self.warnings.append('Detected change to DEPS but couldn\'t find '
2220 'matching change to .DEPS.git') 2223 'matching change to .DEPS.git')
2221 return (bad_revision, good_revision) 2224 return (bad_revision, good_revision)
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2331 cwd = os.getcwd() 2334 cwd = os.getcwd()
2332 self.ChangeToDepotWorkingDirectory(target_depot) 2335 self.ChangeToDepotWorkingDirectory(target_depot)
2333 2336
2334 # If they passed SVN revisions, we can try match them to git SHA1 hashes. 2337 # If they passed SVN revisions, we can try match them to git SHA1 hashes.
2335 bad_revision = self.source_control.ResolveToRevision( 2338 bad_revision = self.source_control.ResolveToRevision(
2336 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100) 2339 bad_revision_in, target_depot, DEPOT_DEPS_NAME, 100)
2337 good_revision = self.source_control.ResolveToRevision( 2340 good_revision = self.source_control.ResolveToRevision(
2338 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100) 2341 good_revision_in, target_depot, DEPOT_DEPS_NAME, -100)
2339 2342
2340 os.chdir(cwd) 2343 os.chdir(cwd)
2341
2342 if bad_revision is None: 2344 if bad_revision is None:
2343 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in 2345 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % bad_revision_in
2344 return results 2346 return results
2345 2347
2346 if good_revision is None: 2348 if good_revision is None:
2347 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in 2349 results['error'] = 'Couldn\'t resolve [%s] to SHA1.' % good_revision_in
2348 return results 2350 return results
2349 2351
2350 # Check that they didn't accidentally swap good and bad revisions. 2352 # Check that they didn't accidentally swap good and bad revisions.
2351 if not self.CheckIfRevisionsInProperOrder( 2353 if not self.CheckIfRevisionsInProperOrder(
2352 target_depot, good_revision, bad_revision): 2354 target_depot, good_revision, bad_revision):
2353 results['error'] = ('bad_revision < good_revision, did you swap these ' 2355 results['error'] = ('bad_revision < good_revision, did you swap these '
2354 'by mistake?') 2356 'by mistake?')
2355 return results 2357 return results
2356
2357 bad_revision, good_revision = self.NudgeRevisionsIfDEPSChange( 2358 bad_revision, good_revision = self.NudgeRevisionsIfDEPSChange(
2358 bad_revision, good_revision) 2359 bad_revision, good_revision, good_revision_in)
2359
2360 if self.opts.output_buildbot_annotations: 2360 if self.opts.output_buildbot_annotations:
2361 bisect_utils.OutputAnnotationStepStart('Gathering Revisions') 2361 bisect_utils.OutputAnnotationStepStart('Gathering Revisions')
2362 2362
2363 cannot_bisect = self.CanPerformBisect(good_revision) 2363 cannot_bisect = self.CanPerformBisect(good_revision)
2364 if cannot_bisect: 2364 if cannot_bisect:
2365 results['error'] = cannot_bisect.get('error') 2365 results['error'] = cannot_bisect.get('error')
2366 return results 2366 return results
2367 2367
2368 print 'Gathering revision range for bisection.' 2368 print 'Gathering revision range for bisection.'
2369 # Retrieve a list of revisions to do bisection on. 2369 # Retrieve a list of revisions to do bisection on.
(...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after
3362 # bugs. If you change this, please update the perf dashboard as well. 3362 # bugs. If you change this, please update the perf dashboard as well.
3363 bisect_utils.OutputAnnotationStepStart('Results') 3363 bisect_utils.OutputAnnotationStepStart('Results')
3364 print 'Error: %s' % e.message 3364 print 'Error: %s' % e.message
3365 if opts.output_buildbot_annotations: 3365 if opts.output_buildbot_annotations:
3366 bisect_utils.OutputAnnotationStepClosed() 3366 bisect_utils.OutputAnnotationStepClosed()
3367 return 1 3367 return 1
3368 3368
3369 3369
3370 if __name__ == '__main__': 3370 if __name__ == '__main__':
3371 sys.exit(main()) 3371 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/auto_bisect/source_control.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698