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

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

Issue 994183002: Make android-chrome bisect work with archives. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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 2013 The Chromium Authors. All rights reserved. 2 # Copyright 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 """Chromium auto-bisect tool 6 """Chromium auto-bisect tool
7 7
8 This script bisects a range of commits using binary search. It starts by getting 8 This script bisects a range of commits using binary search. It starts by getting
9 reference values for the specified "good" and "bad" commits. Then, for revisions 9 reference values for the specified "good" and "bad" commits. Then, for revisions
10 in between, it will get builds, run tests and classify intermediate revisions as 10 in between, it will get builds, run tests and classify intermediate revisions as
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 118
119 # Git branch name used to run bisect try jobs. 119 # Git branch name used to run bisect try jobs.
120 BISECT_TRYJOB_BRANCH = 'bisect-tryjob' 120 BISECT_TRYJOB_BRANCH = 'bisect-tryjob'
121 # Git master branch name. 121 # Git master branch name.
122 BISECT_MASTER_BRANCH = 'master' 122 BISECT_MASTER_BRANCH = 'master'
123 # File to store 'git diff' content. 123 # File to store 'git diff' content.
124 BISECT_PATCH_FILE = 'deps_patch.txt' 124 BISECT_PATCH_FILE = 'deps_patch.txt'
125 # SVN repo where the bisect try jobs are submitted. 125 # SVN repo where the bisect try jobs are submitted.
126 PERF_SVN_REPO_URL = 'svn://svn.chromium.org/chrome-try/try-perf' 126 PERF_SVN_REPO_URL = 'svn://svn.chromium.org/chrome-try/try-perf'
127 FULL_SVN_REPO_URL = 'svn://svn.chromium.org/chrome-try/try' 127 FULL_SVN_REPO_URL = 'svn://svn.chromium.org/chrome-try/try'
128 128 ANDROID_CHROME_SVN_REPO_URL = ('svn://svn.chromium.org/chrome-try-internal/'
129 'try-perf')
129 130
130 class RunGitError(Exception): 131 class RunGitError(Exception):
131 132
132 def __str__(self): 133 def __str__(self):
133 return '%s\nError executing git command.' % self.args[0] 134 return '%s\nError executing git command.' % self.args[0]
134 135
135 136
136 def GetSHA1HexDigest(contents): 137 def GetSHA1HexDigest(contents):
137 """Returns SHA1 hex digest of the given string.""" 138 """Returns SHA1 hex digest of the given string."""
138 return hashlib.sha1(contents).hexdigest() 139 return hashlib.sha1(contents).hexdigest()
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 # the DEPS file with the following format: 189 # the DEPS file with the following format:
189 # 'depot_name': 'revision', 190 # 'depot_name': 'revision',
190 vars_body = re_results.group('vars_body') 191 vars_body = re_results.group('vars_body')
191 rxp = re.compile(r"'(?P<depot_body>[\w_-]+)':[\s]+'(?P<rev_body>[\w@]+)'", 192 rxp = re.compile(r"'(?P<depot_body>[\w_-]+)':[\s]+'(?P<rev_body>[\w@]+)'",
192 re.MULTILINE) 193 re.MULTILINE)
193 re_results = rxp.findall(vars_body) 194 re_results = rxp.findall(vars_body)
194 195
195 return dict(re_results) 196 return dict(re_results)
196 197
197 198
198 def _WaitUntilBuildIsReady(fetch_build_func, builder_name, builder_type, 199 def _WaitUntilBuildIsReady(fetch_build_func, builder_name, build_request_id,
199 build_request_id, max_timeout): 200 max_timeout, buildbot_server_url):
200 """Waits until build is produced by bisect builder on try server. 201 """Waits until build is produced by bisect builder on try server.
201 202
202 Args: 203 Args:
203 fetch_build_func: Function to check and download build from cloud storage. 204 fetch_build_func: Function to check and download build from cloud storage.
204 builder_name: Builder bot name on try server. 205 builder_name: Builder bot name on try server.
205 builder_type: Builder type, e.g. "perf" or "full". Refer to the constants
206 |fetch_build| which determine the valid values that can be passed.
207 build_request_id: A unique ID of the build request posted to try server. 206 build_request_id: A unique ID of the build request posted to try server.
208 max_timeout: Maximum time to wait for the build. 207 max_timeout: Maximum time to wait for the build.
208 buildbot_server_url: Buildbot url to check build status.
209 209
210 Returns: 210 Returns:
211 Downloaded archive file path if exists, otherwise None. 211 Downloaded archive file path if exists, otherwise None.
212 """ 212 """
213 # Build number on the try server. 213 # Build number on the try server.
214 build_num = None 214 build_num = None
215 # Interval to check build on cloud storage. 215 # Interval to check build on cloud storage.
216 poll_interval = 60 216 poll_interval = 60
217 # Interval to check build status on try server in seconds. 217 # Interval to check build status on try server in seconds.
218 status_check_interval = 600 218 status_check_interval = 600
219 last_status_check = time.time() 219 last_status_check = time.time()
220 start_time = time.time() 220 start_time = time.time()
221
221 while True: 222 while True:
222 # Checks for build on gs://chrome-perf and download if exists. 223 # Checks for build on gs://chrome-perf and download if exists.
223 res = fetch_build_func() 224 res = fetch_build_func()
224 if res: 225 if res:
225 return (res, 'Build successfully found') 226 return (res, 'Build successfully found')
226 elapsed_status_check = time.time() - last_status_check 227 elapsed_status_check = time.time() - last_status_check
227 # To avoid overloading try server with status check requests, we check 228 # To avoid overloading try server with status check requests, we check
228 # build status for every 10 minutes. 229 # build status for every 10 minutes.
229 if elapsed_status_check > status_check_interval: 230 if elapsed_status_check > status_check_interval:
230 last_status_check = time.time() 231 last_status_check = time.time()
231 if not build_num: 232 if not build_num:
232 # Get the build number on try server for the current build. 233 # Get the build number on try server for the current build.
233 build_num = request_build.GetBuildNumFromBuilder( 234 build_num = request_build.GetBuildNumFromBuilder(
234 build_request_id, builder_name, builder_type) 235 build_request_id, builder_name, buildbot_server_url)
235 # Check the status of build using the build number. 236 # Check the status of build using the build number.
236 # Note: Build is treated as PENDING if build number is not found 237 # Note: Build is treated as PENDING if build number is not found
237 # on the the try server. 238 # on the the try server.
238 build_status, status_link = request_build.GetBuildStatus( 239 build_status, status_link = request_build.GetBuildStatus(
239 build_num, builder_name, builder_type) 240 build_num, builder_name, buildbot_server_url)
240 if build_status == request_build.FAILED: 241 if build_status == request_build.FAILED:
241 return (None, 'Failed to produce build, log: %s' % status_link) 242 return (None, 'Failed to produce build, log: %s' % status_link)
242 elapsed_time = time.time() - start_time 243 elapsed_time = time.time() - start_time
243 if elapsed_time > max_timeout: 244 if elapsed_time > max_timeout:
244 return (None, 'Timed out: %ss without build' % max_timeout) 245 return (None, 'Timed out: %ss without build' % max_timeout)
245 246
246 logging.info('Time elapsed: %ss without build.', elapsed_time) 247 logging.info('Time elapsed: %ss without build.', elapsed_time)
247 time.sleep(poll_interval) 248 time.sleep(poll_interval)
248 # For some reason, mac bisect bots were not flushing stdout periodically. 249 # For some reason, mac bisect bots were not flushing stdout periodically.
249 # As a result buildbot command is timed-out. Flush stdout on all platforms 250 # As a result buildbot command is timed-out. Flush stdout on all platforms
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 bisect_utils.RunGit(['checkout', '-f', BISECT_MASTER_BRANCH]) 641 bisect_utils.RunGit(['checkout', '-f', BISECT_MASTER_BRANCH])
641 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH]) 642 bisect_utils.RunGit(['branch', '-D', BISECT_TRYJOB_BRANCH])
642 643
643 644
644 def _TryJobSvnRepo(builder_type): 645 def _TryJobSvnRepo(builder_type):
645 """Returns an SVN repo to use for try jobs based on the builder type.""" 646 """Returns an SVN repo to use for try jobs based on the builder type."""
646 if builder_type == fetch_build.PERF_BUILDER: 647 if builder_type == fetch_build.PERF_BUILDER:
647 return PERF_SVN_REPO_URL 648 return PERF_SVN_REPO_URL
648 if builder_type == fetch_build.FULL_BUILDER: 649 if builder_type == fetch_build.FULL_BUILDER:
649 return FULL_SVN_REPO_URL 650 return FULL_SVN_REPO_URL
651 if builder_type == fetch_build.ANDROID_CHROME_PERF_BUILDER:
652 return ANDROID_CHROME_SVN_REPO_URL
650 raise NotImplementedError('Unknown builder type "%s".' % builder_type) 653 raise NotImplementedError('Unknown builder type "%s".' % builder_type)
651 654
652 655
653 class BisectPerformanceMetrics(object): 656 class BisectPerformanceMetrics(object):
654 """This class contains functionality to perform a bisection of a range of 657 """This class contains functionality to perform a bisection of a range of
655 revisions to narrow down where performance regressions may have occurred. 658 revisions to narrow down where performance regressions may have occurred.
656 659
657 The main entry-point is the Run method. 660 The main entry-point is the Run method.
658 """ 661 """
659 662
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 revision: The git revision to download. 810 revision: The git revision to download.
808 depot: The name of a dependency repository. Should be in DEPOT_NAMES. 811 depot: The name of a dependency repository. Should be in DEPOT_NAMES.
809 build_type: Target build type, e.g. Release', 'Debug', 'Release_x64' etc. 812 build_type: Target build type, e.g. Release', 'Debug', 'Release_x64' etc.
810 create_patch: Create a patch with any locally modified files. 813 create_patch: Create a patch with any locally modified files.
811 814
812 Returns: 815 Returns:
813 True if download succeeds, otherwise False. 816 True if download succeeds, otherwise False.
814 """ 817 """
815 patch = None 818 patch = None
816 patch_sha = None 819 patch_sha = None
817 if depot != 'chromium': 820 if depot not in ('chromium', 'android-chrome'):
818 # Create a DEPS patch with new revision for dependency repository. 821 # Create a DEPS patch with new revision for dependency repository.
819 self._CreateDEPSPatch(depot, revision) 822 self._CreateDEPSPatch(depot, revision)
820 create_patch = True 823 create_patch = True
821 824
822 if create_patch: 825 if create_patch:
823 revision, patch = self._CreatePatch(revision) 826 revision, patch = self._CreatePatch(revision)
824 827
825 if patch: 828 if patch:
826 # Get the SHA of the DEPS changes patch. 829 # Get the SHA of the DEPS changes patch.
827 patch_sha = GetSHA1HexDigest(patch) 830 patch_sha = GetSHA1HexDigest(patch)
(...skipping 24 matching lines...) Expand all
852 the DEPS, if applicable. 855 the DEPS, if applicable.
853 deps_patch_sha: The SHA1 hex digest of the above patch. 856 deps_patch_sha: The SHA1 hex digest of the above patch.
854 857
855 Returns: 858 Returns:
856 File path of the downloaded file if successful, otherwise None. 859 File path of the downloaded file if successful, otherwise None.
857 """ 860 """
858 bucket_name, remote_path = fetch_build.GetBucketAndRemotePath( 861 bucket_name, remote_path = fetch_build.GetBucketAndRemotePath(
859 revision, builder_type=self.opts.builder_type, 862 revision, builder_type=self.opts.builder_type,
860 target_arch=self.opts.target_arch, 863 target_arch=self.opts.target_arch,
861 target_platform=self.opts.target_platform, 864 target_platform=self.opts.target_platform,
862 deps_patch_sha=deps_patch_sha) 865 deps_patch_sha=deps_patch_sha,
866 extra_src=self.opts.extra_src)
863 output_dir = os.path.abspath(build_dir) 867 output_dir = os.path.abspath(build_dir)
864 fetch_build_func = lambda: fetch_build.FetchFromCloudStorage( 868 fetch_build_func = lambda: fetch_build.FetchFromCloudStorage(
865 bucket_name, remote_path, output_dir) 869 bucket_name, remote_path, output_dir)
866 870
867 is_available = fetch_build.BuildIsAvailable(bucket_name, remote_path) 871 is_available = fetch_build.BuildIsAvailable(bucket_name, remote_path)
868 if is_available: 872 if is_available:
869 return fetch_build_func() 873 return fetch_build_func()
870 874
871 # When build archive doesn't exist, make a request and wait. 875 # When build archive doesn't exist, make a request and wait.
872 return self._RequestBuildAndWait( 876 return self._RequestBuildAndWait(
(...skipping 28 matching lines...) Expand all
901 # This ID is added to "Reason" property of the build. 905 # This ID is added to "Reason" property of the build.
902 build_request_id = GetSHA1HexDigest( 906 build_request_id = GetSHA1HexDigest(
903 '%s-%s-%s' % (git_revision, deps_patch, time.time())) 907 '%s-%s-%s' % (git_revision, deps_patch, time.time()))
904 908
905 # Revert any changes to DEPS file. 909 # Revert any changes to DEPS file.
906 bisect_utils.CheckRunGit(['reset', '--hard', 'HEAD'], cwd=self.src_cwd) 910 bisect_utils.CheckRunGit(['reset', '--hard', 'HEAD'], cwd=self.src_cwd)
907 911
908 builder_name, build_timeout = fetch_build.GetBuilderNameAndBuildTime( 912 builder_name, build_timeout = fetch_build.GetBuilderNameAndBuildTime(
909 builder_type=self.opts.builder_type, 913 builder_type=self.opts.builder_type,
910 target_arch=self.opts.target_arch, 914 target_arch=self.opts.target_arch,
911 target_platform=self.opts.target_platform) 915 target_platform=self.opts.target_platform,
916 extra_src=self.opts.extra_src)
912 917
913 try: 918 try:
914 _StartBuilderTryJob(self.opts.builder_type, git_revision, builder_name, 919 _StartBuilderTryJob(self.opts.builder_type, git_revision, builder_name,
915 job_name=build_request_id, patch=deps_patch) 920 job_name=build_request_id, patch=deps_patch)
916 except RunGitError as e: 921 except RunGitError as e:
917 logging.warn('Failed to post builder try job for revision: [%s].\n' 922 logging.warn('Failed to post builder try job for revision: [%s].\n'
918 'Error: %s', git_revision, e) 923 'Error: %s', git_revision, e)
919 return None 924 return None
920 925
926 # Get the buildbot master url to monitor build status.
927 buildbot_server_url = fetch_build.GetBuildBotUrl(
928 builder_type=self.opts.builder_type,
929 target_arch=self.opts.target_arch,
930 target_platform=self.opts.target_platform,
931 extra_src=self.opts.extra_src)
932
921 archive_filename, error_msg = _WaitUntilBuildIsReady( 933 archive_filename, error_msg = _WaitUntilBuildIsReady(
922 fetch_build_func, builder_name, self.opts.builder_type, 934 fetch_build_func, builder_name, build_request_id, build_timeout,
923 build_request_id, build_timeout) 935 buildbot_server_url)
924 if not archive_filename: 936 if not archive_filename:
925 logging.warn('%s [revision: %s]', error_msg, git_revision) 937 logging.warn('%s [revision: %s]', error_msg, git_revision)
926 return archive_filename 938 return archive_filename
927 939
928 def _UnzipAndMoveBuildProducts(self, downloaded_file, build_dir, 940 def _UnzipAndMoveBuildProducts(self, downloaded_file, build_dir,
929 build_type='Release'): 941 build_type='Release'):
930 """Unzips the build archive and moves it to the build output directory. 942 """Unzips the build archive and moves it to the build output directory.
931 943
932 The build output directory is wherever the binaries are expected to 944 The build output directory is wherever the binaries are expected to
933 be in order to start Chrome and run tests. 945 be in order to start Chrome and run tests.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 if bisect_utils.IsWindowsHost(): 1011 if bisect_utils.IsWindowsHost():
1000 return 'full-build-win32' 1012 return 'full-build-win32'
1001 if bisect_utils.IsLinuxHost(): 1013 if bisect_utils.IsLinuxHost():
1002 return 'full-build-linux' 1014 return 'full-build-linux'
1003 if bisect_utils.IsMacHost(): 1015 if bisect_utils.IsMacHost():
1004 return 'full-build-mac' 1016 return 'full-build-mac'
1005 raise NotImplementedError('Unknown platform "%s".' % sys.platform) 1017 raise NotImplementedError('Unknown platform "%s".' % sys.platform)
1006 1018
1007 def IsDownloadable(self, depot): 1019 def IsDownloadable(self, depot):
1008 """Checks if build can be downloaded based on target platform and depot.""" 1020 """Checks if build can be downloaded based on target platform and depot."""
1009 if (self.opts.target_platform in ['chromium', 'android'] 1021 if (self.opts.target_platform in ['chromium', 'android', 'android-chrome']
1010 and self.opts.builder_type): 1022 and self.opts.builder_type):
1011 return (depot == 'chromium' or 1023 # In case of android-chrome platform, download archives only for
1024 # android-chrome depot; for other depots such as chromium, v8, skia
1025 # etc., build the binary locally.
1026 if self.opts.target_platform == 'android-chrome':
1027 return depot == 'android-chrome'
1028 else:
1029 return (depot == 'chromium' or
1012 'chromium' in bisect_utils.DEPOT_DEPS_NAME[depot]['from'] or 1030 'chromium' in bisect_utils.DEPOT_DEPS_NAME[depot]['from'] or
1013 'v8' in bisect_utils.DEPOT_DEPS_NAME[depot]['from']) 1031 'v8' in bisect_utils.DEPOT_DEPS_NAME[depot]['from'])
1014 return False 1032 return False
1015 1033
1016 def UpdateDepsContents(self, deps_contents, depot, git_revision, deps_key): 1034 def UpdateDepsContents(self, deps_contents, depot, git_revision, deps_key):
1017 """Returns modified version of DEPS file contents. 1035 """Returns modified version of DEPS file contents.
1018 1036
1019 Args: 1037 Args:
1020 deps_contents: DEPS file content. 1038 deps_contents: DEPS file content.
1021 depot: Current depot being bisected. 1039 depot: Current depot being bisected.
(...skipping 1802 matching lines...) Expand 10 before | Expand all | Expand 10 after
2824 # bugs. If you change this, please update the perf dashboard as well. 2842 # bugs. If you change this, please update the perf dashboard as well.
2825 bisect_utils.OutputAnnotationStepStart('Results') 2843 bisect_utils.OutputAnnotationStepStart('Results')
2826 print 'Runtime Error: %s' % e 2844 print 'Runtime Error: %s' % e
2827 if opts.output_buildbot_annotations: 2845 if opts.output_buildbot_annotations:
2828 bisect_utils.OutputAnnotationStepClosed() 2846 bisect_utils.OutputAnnotationStepClosed()
2829 return 1 2847 return 1
2830 2848
2831 2849
2832 if __name__ == '__main__': 2850 if __name__ == '__main__':
2833 sys.exit(main()) 2851 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