| OLD | NEW |
| 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 'from': ['chromium'], | 145 'from': ['chromium'], |
| 146 'viewvc': 'https://code.google.com/p/skia/source/detail?r=', | 146 'viewvc': 'https://code.google.com/p/skia/source/detail?r=', |
| 147 'deps_var': 'None' | 147 'deps_var': 'None' |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 | 150 |
| 151 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() | 151 DEPOT_NAMES = DEPOT_DEPS_NAME.keys() |
| 152 | 152 |
| 153 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' | 153 CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome' |
| 154 | 154 |
| 155 # Possible return values from BisectPerformanceMetrics.SyncBuildAndRunRevision. | 155 # Possible return values from BisectPerformanceMetrics.RunTest. |
| 156 BUILD_RESULT_SUCCEED = 0 | 156 BUILD_RESULT_SUCCEED = 0 |
| 157 BUILD_RESULT_FAIL = 1 | 157 BUILD_RESULT_FAIL = 1 |
| 158 BUILD_RESULT_SKIPPED = 2 | 158 BUILD_RESULT_SKIPPED = 2 |
| 159 | 159 |
| 160 # Maximum time in seconds to wait after posting build request to the try server. | 160 # Maximum time in seconds to wait after posting build request to the try server. |
| 161 # TODO: Change these values based on the actual time taken by buildbots on | 161 # TODO: Change these values based on the actual time taken by buildbots on |
| 162 # the try server. | 162 # the try server. |
| 163 MAX_MAC_BUILD_TIME = 14400 | 163 MAX_MAC_BUILD_TIME = 14400 |
| 164 MAX_WIN_BUILD_TIME = 14400 | 164 MAX_WIN_BUILD_TIME = 14400 |
| 165 MAX_LINUX_BUILD_TIME = 14400 | 165 MAX_LINUX_BUILD_TIME = 14400 |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 results['chromium'] = output.strip() | 1180 results['chromium'] = output.strip() |
| 1181 | 1181 |
| 1182 if depot == 'v8': | 1182 if depot == 'v8': |
| 1183 # We can't try to map the trunk revision to bleeding edge yet, because | 1183 # We can't try to map the trunk revision to bleeding edge yet, because |
| 1184 # we don't know which direction to try to search in. Have to wait until | 1184 # we don't know which direction to try to search in. Have to wait until |
| 1185 # the bisect has narrowed the results down to 2 v8 rolls. | 1185 # the bisect has narrowed the results down to 2 v8 rolls. |
| 1186 results['v8_bleeding_edge'] = None | 1186 results['v8_bleeding_edge'] = None |
| 1187 | 1187 |
| 1188 return results | 1188 return results |
| 1189 | 1189 |
| 1190 def BackupOrRestoreOutputdirectory(self, restore=False, build_type='Release'): | 1190 def BackupOrRestoreOutputDirectory(self, restore=False, build_type='Release'): |
| 1191 """Backs up or restores build output directory based on restore argument. | 1191 """Backs up or restores build output directory based on restore argument. |
| 1192 | 1192 |
| 1193 Args: | 1193 Args: |
| 1194 restore: Indicates whether to restore or backup. Default is False(Backup) | 1194 restore: Indicates whether to restore or backup. Default is False(Backup) |
| 1195 build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) | 1195 build_type: Target build type ('Release', 'Debug', 'Release_x64' etc.) |
| 1196 | 1196 |
| 1197 Returns: | 1197 Returns: |
| 1198 Path to backup or restored location as string. otherwise None if it fails. | 1198 Path to backup or restored location as string. otherwise None if it fails. |
| 1199 """ | 1199 """ |
| 1200 build_dir = os.path.abspath( | 1200 build_dir = os.path.abspath( |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 revision, fetch_build=fetch_build_func, patch=patch) | 1278 revision, fetch_build=fetch_build_func, patch=patch) |
| 1279 if not downloaded_file: | 1279 if not downloaded_file: |
| 1280 return False | 1280 return False |
| 1281 | 1281 |
| 1282 # Generic name for the archive, created when archive file is extracted. | 1282 # Generic name for the archive, created when archive file is extracted. |
| 1283 output_dir = os.path.join( | 1283 output_dir = os.path.join( |
| 1284 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch)) | 1284 abs_build_dir, GetZipFileName(target_arch=self.opts.target_arch)) |
| 1285 # Unzip build archive directory. | 1285 # Unzip build archive directory. |
| 1286 try: | 1286 try: |
| 1287 RmTreeAndMkDir(output_dir, skip_makedir=True) | 1287 RmTreeAndMkDir(output_dir, skip_makedir=True) |
| 1288 self.BackupOrRestoreOutputdirectory(restore=False) | 1288 self.BackupOrRestoreOutputDirectory(restore=False) |
| 1289 # Build output directory based on target(e.g. out/Release, out/Debug). | 1289 # Build output directory based on target(e.g. out/Release, out/Debug). |
| 1290 target_build_output_dir = os.path.join(abs_build_dir, build_type) | 1290 target_build_output_dir = os.path.join(abs_build_dir, build_type) |
| 1291 ExtractZip(downloaded_file, abs_build_dir) | 1291 ExtractZip(downloaded_file, abs_build_dir) |
| 1292 if not os.path.exists(output_dir): | 1292 if not os.path.exists(output_dir): |
| 1293 # Due to recipe changes, the builds extract folder contains | 1293 # Due to recipe changes, the builds extract folder contains |
| 1294 # out/Release instead of full-build-<platform>/Release. | 1294 # out/Release instead of full-build-<platform>/Release. |
| 1295 if os.path.exists(os.path.join(abs_build_dir, 'out', build_type)): | 1295 if os.path.exists(os.path.join(abs_build_dir, 'out', build_type)): |
| 1296 output_dir = os.path.join(abs_build_dir, 'out', build_type) | 1296 output_dir = os.path.join(abs_build_dir, 'out', build_type) |
| 1297 else: | 1297 else: |
| 1298 raise IOError('Missing extracted folder %s ' % output_dir) | 1298 raise IOError('Missing extracted folder %s ' % output_dir) |
| 1299 | 1299 |
| 1300 print 'Moving build from %s to %s' % ( | 1300 print 'Moving build from %s to %s' % ( |
| 1301 output_dir, target_build_output_dir) | 1301 output_dir, target_build_output_dir) |
| 1302 shutil.move(output_dir, target_build_output_dir) | 1302 shutil.move(output_dir, target_build_output_dir) |
| 1303 return True | 1303 return True |
| 1304 except Exception as e: | 1304 except Exception as e: |
| 1305 print 'Something went wrong while extracting archive file: %s' % e | 1305 print 'Something went wrong while extracting archive file: %s' % e |
| 1306 self.BackupOrRestoreOutputdirectory(restore=True) | 1306 self.BackupOrRestoreOutputDirectory(restore=True) |
| 1307 # Cleanup any leftovers from unzipping. | 1307 # Cleanup any leftovers from unzipping. |
| 1308 if os.path.exists(output_dir): | 1308 if os.path.exists(output_dir): |
| 1309 RmTreeAndMkDir(output_dir, skip_makedir=True) | 1309 RmTreeAndMkDir(output_dir, skip_makedir=True) |
| 1310 finally: | 1310 finally: |
| 1311 # Delete downloaded archive | 1311 # Delete downloaded archive |
| 1312 if os.path.exists(downloaded_file): | 1312 if os.path.exists(downloaded_file): |
| 1313 os.remove(downloaded_file) | 1313 os.remove(downloaded_file) |
| 1314 return False | 1314 return False |
| 1315 | 1315 |
| 1316 def PostBuildRequestAndWait(self, git_revision, fetch_build, patch=None): | 1316 def PostBuildRequestAndWait(self, git_revision, fetch_build, patch=None): |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 'std_err': standard_err, | 1704 'std_err': standard_err, |
| 1705 'std_dev': standard_dev, | 1705 'std_dev': standard_dev, |
| 1706 'values': metric_values, | 1706 'values': metric_values, |
| 1707 } | 1707 } |
| 1708 | 1708 |
| 1709 print 'Results of performance test: %12f %12f' % ( | 1709 print 'Results of performance test: %12f %12f' % ( |
| 1710 truncated_mean, standard_err) | 1710 truncated_mean, standard_err) |
| 1711 print | 1711 print |
| 1712 return (values, success_code, output_of_all_runs) | 1712 return (values, success_code, output_of_all_runs) |
| 1713 | 1713 |
| 1714 def FindAllRevisionsToSync(self, revision, depot): | 1714 def _FindAllRevisionsToSync(self, revision, depot): |
| 1715 """Finds all dependent revisions and depots that need to be synced. | 1715 """Finds all dependent revisions and depots that need to be synced. |
| 1716 | 1716 |
| 1717 For example skia is broken up into 3 git mirrors over skia/src, | 1717 For example skia is broken up into 3 git mirrors over skia/src, |
| 1718 skia/gyp, and skia/include. To sync skia/src properly, one has to find | 1718 skia/gyp, and skia/include. To sync skia/src properly, one has to find |
| 1719 the proper revisions in skia/gyp and skia/include. | 1719 the proper revisions in skia/gyp and skia/include. |
| 1720 | 1720 |
| 1721 This is only useful in the git workflow, as an SVN depot may be split into | 1721 This is only useful in the git workflow, as an SVN depot may be split into |
| 1722 multiple mirrors. | 1722 multiple mirrors. |
| 1723 | 1723 |
| 1724 Args: | 1724 Args: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 Returns: | 1792 Returns: |
| 1793 True if successful. | 1793 True if successful. |
| 1794 """ | 1794 """ |
| 1795 cwd = os.getcwd() | 1795 cwd = os.getcwd() |
| 1796 self.ChangeToDepotWorkingDirectory('cros') | 1796 self.ChangeToDepotWorkingDirectory('cros') |
| 1797 cmd = [bisect_utils.CROS_SDK_PATH, '--create'] | 1797 cmd = [bisect_utils.CROS_SDK_PATH, '--create'] |
| 1798 return_code = bisect_utils.RunProcess(cmd) | 1798 return_code = bisect_utils.RunProcess(cmd) |
| 1799 os.chdir(cwd) | 1799 os.chdir(cwd) |
| 1800 return not return_code | 1800 return not return_code |
| 1801 | 1801 |
| 1802 def PerformPreSyncCleanup(self, revision, depot): | 1802 def _PerformPreSyncCleanup(self, depot): |
| 1803 """Performs any necessary cleanup before syncing. | 1803 """Performs any necessary cleanup before syncing. |
| 1804 | 1804 |
| 1805 Args: |
| 1806 depot: Depot name. |
| 1807 |
| 1805 Returns: | 1808 Returns: |
| 1806 True if successful. | 1809 True if successful. |
| 1807 """ | 1810 """ |
| 1808 if depot == 'chromium' or depot == 'android-chrome': | 1811 if depot == 'chromium' or depot == 'android-chrome': |
| 1809 # Removes third_party/libjingle. At some point, libjingle was causing | 1812 # Removes third_party/libjingle. At some point, libjingle was causing |
| 1810 # issues syncing when using the git workflow (crbug.com/266324). | 1813 # issues syncing when using the git workflow (crbug.com/266324). |
| 1811 os.chdir(self.src_cwd) | 1814 os.chdir(self.src_cwd) |
| 1812 if not bisect_utils.RemoveThirdPartyDirectory('libjingle'): | 1815 if not bisect_utils.RemoveThirdPartyDirectory('libjingle'): |
| 1813 return False | 1816 return False |
| 1814 # Removes third_party/skia. At some point, skia was causing | 1817 # Removes third_party/skia. At some point, skia was causing |
| 1815 # issues syncing when using the git workflow (crbug.com/377951). | 1818 # issues syncing when using the git workflow (crbug.com/377951). |
| 1816 if not bisect_utils.RemoveThirdPartyDirectory('skia'): | 1819 if not bisect_utils.RemoveThirdPartyDirectory('skia'): |
| 1817 return False | 1820 return False |
| 1818 elif depot == 'cros': | 1821 elif depot == 'cros': |
| 1819 return self.PerformCrosChrootCleanup() | 1822 return self.PerformCrosChrootCleanup() |
| 1820 return True | 1823 return True |
| 1821 | 1824 |
| 1822 def RunPostSync(self, depot): | 1825 def _RunPostSync(self, depot): |
| 1823 """Performs any work after syncing. | 1826 """Performs any work after syncing. |
| 1824 | 1827 |
| 1828 Args: |
| 1829 depot: Depot name. |
| 1830 |
| 1825 Returns: | 1831 Returns: |
| 1826 True if successful. | 1832 True if successful. |
| 1827 """ | 1833 """ |
| 1828 if self.opts.target_platform == 'android': | 1834 if self.opts.target_platform == 'android': |
| 1829 if not builder.SetupAndroidBuildEnvironment(self.opts, | 1835 if not builder.SetupAndroidBuildEnvironment(self.opts, |
| 1830 path_to_src=self.src_cwd): | 1836 path_to_src=self.src_cwd): |
| 1831 return False | 1837 return False |
| 1832 | 1838 |
| 1833 if depot == 'cros': | 1839 if depot == 'cros': |
| 1834 return self.CreateCrosChroot() | 1840 return self.CreateCrosChroot() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1854 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] | 1860 cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision] |
| 1855 output = bisect_utils.CheckRunGit(cmd) | 1861 output = bisect_utils.CheckRunGit(cmd) |
| 1856 | 1862 |
| 1857 files = output.splitlines() | 1863 files = output.splitlines() |
| 1858 | 1864 |
| 1859 if len(files) == 1 and files[0] == 'DEPS': | 1865 if len(files) == 1 and files[0] == 'DEPS': |
| 1860 return True | 1866 return True |
| 1861 | 1867 |
| 1862 return False | 1868 return False |
| 1863 | 1869 |
| 1864 def SyncBuildAndRunRevision(self, revision, depot, command_to_run, metric, | 1870 def RunTest(self, revision, depot, command, metric, skippable=False): |
| 1865 skippable=False): | |
| 1866 """Performs a full sync/build/run of the specified revision. | 1871 """Performs a full sync/build/run of the specified revision. |
| 1867 | 1872 |
| 1868 Args: | 1873 Args: |
| 1869 revision: The revision to sync to. | 1874 revision: The revision to sync to. |
| 1870 depot: The depot that's being used at the moment (src, webkit, etc.) | 1875 depot: The depot that's being used at the moment (src, webkit, etc.) |
| 1871 command_to_run: The command to execute the performance test. | 1876 command: The command to execute the performance test. |
| 1872 metric: The performance metric being tested. | 1877 metric: The performance metric being tested. |
| 1873 | 1878 |
| 1874 Returns: | 1879 Returns: |
| 1875 On success, a tuple containing the results of the performance test. | 1880 On success, a tuple containing the results of the performance test. |
| 1876 Otherwise, a tuple with the error message. | 1881 Otherwise, a tuple with the error message. |
| 1877 """ | 1882 """ |
| 1883 # Decide which sync program to use. |
| 1878 sync_client = None | 1884 sync_client = None |
| 1879 if depot == 'chromium' or depot == 'android-chrome': | 1885 if depot == 'chromium' or depot == 'android-chrome': |
| 1880 sync_client = 'gclient' | 1886 sync_client = 'gclient' |
| 1881 elif depot == 'cros': | 1887 elif depot == 'cros': |
| 1882 sync_client = 'repo' | 1888 sync_client = 'repo' |
| 1883 | 1889 |
| 1884 revisions_to_sync = self.FindAllRevisionsToSync(revision, depot) | 1890 # Decide what depots will need to be synced to what revisions. |
| 1885 | 1891 revisions_to_sync = self._FindAllRevisionsToSync(revision, depot) |
| 1886 if not revisions_to_sync: | 1892 if not revisions_to_sync: |
| 1887 return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL) | 1893 return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL) |
| 1888 | 1894 |
| 1889 if not self.PerformPreSyncCleanup(revision, depot): | 1895 if not self._PerformPreSyncCleanup(depot): |
| 1890 return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL) | 1896 return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL) |
| 1891 | 1897 |
| 1892 success = True | 1898 # Do the syncing for all depots. |
| 1899 if not self.opts.debug_ignore_sync: |
| 1900 if not self._SyncAllRevisions(revisions_to_sync, sync_client): |
| 1901 return ('Failed to sync: [%s]' % str(revision), BUILD_RESULT_FAIL) |
| 1893 | 1902 |
| 1894 if not self.opts.debug_ignore_sync: | 1903 # Try to do any post-sync steps. This may include "gclient runhooks". |
| 1895 for r in revisions_to_sync: | 1904 if not self._RunPostSync(depot): |
| 1896 self.ChangeToDepotWorkingDirectory(r[0]) | 1905 return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL) |
| 1897 | 1906 |
| 1898 if sync_client: | 1907 # Skip this revision if it can be skipped. |
| 1899 self.PerformPreBuildCleanup() | 1908 if skippable and self.ShouldSkipRevision(depot, revision): |
| 1909 return ('Skipped revision: [%s]' % str(revision), |
| 1910 BUILD_RESULT_SKIPPED) |
| 1900 | 1911 |
| 1901 # If you're using gclient to sync, you need to specify the depot you | 1912 # Obtain a build for this revision. This may be done by requesting a build |
| 1902 # want so that all the dependencies sync properly as well. | 1913 # from another builder, waiting for it and downloading it. |
| 1903 # i.e. gclient sync src@<SHA1> | 1914 start_build_time = time.time() |
| 1904 current_revision = r[1] | 1915 build_success = self.BuildCurrentRevision(depot, revision) |
| 1905 if sync_client == 'gclient': | 1916 if not build_success: |
| 1906 current_revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], | 1917 return ('Failed to build revision: [%s]' % str(revision), |
| 1907 current_revision) | 1918 BUILD_RESULT_FAIL) |
| 1908 if not self.source_control.SyncToRevision(current_revision, | 1919 after_build_time = time.time() |
| 1909 sync_client): | |
| 1910 success = False | |
| 1911 | 1920 |
| 1912 break | 1921 # Possibly alter the command. |
| 1922 command = self.GetCompatibleCommand(command, revision, depot) |
| 1913 | 1923 |
| 1914 if success: | 1924 # Run the command and get the results. |
| 1915 success = self.RunPostSync(depot) | 1925 results = self.RunPerformanceTestAndParseResults(command, metric) |
| 1916 if success: | |
| 1917 if skippable and self.ShouldSkipRevision(depot, revision): | |
| 1918 return ('Skipped revision: [%s]' % str(revision), | |
| 1919 BUILD_RESULT_SKIPPED) | |
| 1920 | 1926 |
| 1921 start_build_time = time.time() | 1927 # Restore build output directory once the tests are done, to avoid |
| 1922 if self.BuildCurrentRevision(depot, revision): | 1928 # any discrepancies. |
| 1923 after_build_time = time.time() | 1929 if self.IsDownloadable(depot) and revision: |
| 1924 # Hack to support things that got changed. | 1930 self.BackupOrRestoreOutputDirectory(restore=True) |
| 1925 command_to_run = self.GetCompatibleCommand( | |
| 1926 command_to_run, revision, depot) | |
| 1927 results = self.RunPerformanceTestAndParseResults(command_to_run, | |
| 1928 metric) | |
| 1929 # Restore build output directory once the tests are done, to avoid | |
| 1930 # any discrepancies. | |
| 1931 if self.IsDownloadable(depot) and revision: | |
| 1932 self.BackupOrRestoreOutputdirectory(restore=True) | |
| 1933 | 1931 |
| 1934 if results[1] == 0: | 1932 # A value other than 0 indicates that the test couldn't be run, and results |
| 1935 external_revisions = self._Get3rdPartyRevisions(depot) | 1933 # should also include an error message. |
| 1934 if results[1] != 0: |
| 1935 return results |
| 1936 | 1936 |
| 1937 if not external_revisions is None: | 1937 external_revisions = self._Get3rdPartyRevisions(depot) |
| 1938 return (results[0], results[1], external_revisions, | 1938 |
| 1939 time.time() - after_build_time, after_build_time - | 1939 if not external_revisions is None: |
| 1940 start_build_time) | 1940 return (results[0], results[1], external_revisions, |
| 1941 else: | 1941 time.time() - after_build_time, after_build_time - |
| 1942 return ('Failed to parse DEPS file for external revisions.', | 1942 start_build_time) |
| 1943 BUILD_RESULT_FAIL) | |
| 1944 else: | |
| 1945 return results | |
| 1946 else: | |
| 1947 return ('Failed to build revision: [%s]' % str(revision), | |
| 1948 BUILD_RESULT_FAIL) | |
| 1949 else: | |
| 1950 return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL) | |
| 1951 else: | 1943 else: |
| 1952 return ('Failed to sync revision: [%s]' % str(revision), | 1944 return ('Failed to parse DEPS file for external revisions.', |
| 1953 BUILD_RESULT_FAIL) | 1945 BUILD_RESULT_FAIL) |
| 1946 |
| 1947 def _SyncAllRevisions(self, revisions_to_sync, sync_client): |
| 1948 """Syncs multiple depots to particular revisions. |
| 1949 |
| 1950 Args: |
| 1951 revisions_to_sync: A list of (depot, revision) pairs to be synced. |
| 1952 sync_client: Program used to sync, e.g. "gclient", "repo". Can be None. |
| 1953 |
| 1954 Returns: |
| 1955 True if successful, False otherwise. |
| 1956 """ |
| 1957 for depot, revision in revisions_to_sync: |
| 1958 self.ChangeToDepotWorkingDirectory(depot) |
| 1959 |
| 1960 if sync_client: |
| 1961 self.PerformPreBuildCleanup() |
| 1962 |
| 1963 # When using gclient to sync, you need to specify the depot you |
| 1964 # want so that all the dependencies sync properly as well. |
| 1965 # i.e. gclient sync src@<SHA1> |
| 1966 if sync_client == 'gclient': |
| 1967 revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision) |
| 1968 |
| 1969 sync_success = self.source_control.SyncToRevision(revision, sync_client) |
| 1970 if not sync_success: |
| 1971 return False |
| 1972 |
| 1973 return True |
| 1954 | 1974 |
| 1955 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): | 1975 def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value): |
| 1956 """Given known good and bad values, decide if the current_value passed | 1976 """Given known good and bad values, decide if the current_value passed |
| 1957 or failed. | 1977 or failed. |
| 1958 | 1978 |
| 1959 Args: | 1979 Args: |
| 1960 current_value: The value of the metric being checked. | 1980 current_value: The value of the metric being checked. |
| 1961 known_bad_value: The reference value for a "failed" run. | 1981 known_bad_value: The reference value for a "failed" run. |
| 1962 known_good_value: The reference value for a "passed" run. | 1982 known_good_value: The reference value for a "passed" run. |
| 1963 | 1983 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 Args: | 2132 Args: |
| 2113 good_rev: The last known good revision where the performance regression | 2133 good_rev: The last known good revision where the performance regression |
| 2114 has not occurred yet. | 2134 has not occurred yet. |
| 2115 bad_rev: A revision where the performance regression has already occurred. | 2135 bad_rev: A revision where the performance regression has already occurred. |
| 2116 cmd: The command to execute the performance test. | 2136 cmd: The command to execute the performance test. |
| 2117 metric: The metric being tested for regression. | 2137 metric: The metric being tested for regression. |
| 2118 | 2138 |
| 2119 Returns: | 2139 Returns: |
| 2120 A tuple with the results of building and running each revision. | 2140 A tuple with the results of building and running each revision. |
| 2121 """ | 2141 """ |
| 2122 bad_run_results = self.SyncBuildAndRunRevision( | 2142 bad_run_results = self.RunTest(bad_rev, target_depot, cmd, metric) |
| 2123 bad_rev, target_depot, cmd, metric) | |
| 2124 | 2143 |
| 2125 good_run_results = None | 2144 good_run_results = None |
| 2126 | 2145 |
| 2127 if not bad_run_results[1]: | 2146 if not bad_run_results[1]: |
| 2128 good_run_results = self.SyncBuildAndRunRevision( | 2147 good_run_results = self.RunTest(good_rev, target_depot, cmd, metric) |
| 2129 good_rev, target_depot, cmd, metric) | |
| 2130 | 2148 |
| 2131 return (bad_run_results, good_run_results) | 2149 return (bad_run_results, good_run_results) |
| 2132 | 2150 |
| 2133 def PrintRevisionsToBisectMessage(self, revision_list, depot): | 2151 def PrintRevisionsToBisectMessage(self, revision_list, depot): |
| 2134 if self.opts.output_buildbot_annotations: | 2152 if self.opts.output_buildbot_annotations: |
| 2135 step_name = 'Bisection Range: [%s - %s]' % ( | 2153 step_name = 'Bisection Range: [%s - %s]' % ( |
| 2136 revision_list[len(revision_list)-1], revision_list[0]) | 2154 revision_list[len(revision_list)-1], revision_list[0]) |
| 2137 bisect_utils.OutputAnnotationStepStart(step_name) | 2155 bisect_utils.OutputAnnotationStepStart(step_name) |
| 2138 | 2156 |
| 2139 print | 2157 print |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 next_revision_depot = next_revision_data['depot'] | 2521 next_revision_depot = next_revision_data['depot'] |
| 2504 | 2522 |
| 2505 self.ChangeToDepotWorkingDirectory(next_revision_depot) | 2523 self.ChangeToDepotWorkingDirectory(next_revision_depot) |
| 2506 | 2524 |
| 2507 if self.opts.output_buildbot_annotations: | 2525 if self.opts.output_buildbot_annotations: |
| 2508 step_name = 'Working on [%s]' % next_revision_id | 2526 step_name = 'Working on [%s]' % next_revision_id |
| 2509 bisect_utils.OutputAnnotationStepStart(step_name) | 2527 bisect_utils.OutputAnnotationStepStart(step_name) |
| 2510 | 2528 |
| 2511 print 'Working on revision: [%s]' % next_revision_id | 2529 print 'Working on revision: [%s]' % next_revision_id |
| 2512 | 2530 |
| 2513 run_results = self.SyncBuildAndRunRevision(next_revision_id, | 2531 run_results = self.RunTest( |
| 2514 next_revision_depot, | 2532 next_revision_id, next_revision_depot, command_to_run, metric, |
| 2515 command_to_run, | 2533 skippable=True) |
| 2516 metric, skippable=True) | |
| 2517 | 2534 |
| 2518 # If the build is successful, check whether or not the metric | 2535 # If the build is successful, check whether or not the metric |
| 2519 # had regressed. | 2536 # had regressed. |
| 2520 if not run_results[1]: | 2537 if not run_results[1]: |
| 2521 if len(run_results) > 2: | 2538 if len(run_results) > 2: |
| 2522 next_revision_data['external'] = run_results[2] | 2539 next_revision_data['external'] = run_results[2] |
| 2523 next_revision_data['perf_time'] = run_results[3] | 2540 next_revision_data['perf_time'] = run_results[3] |
| 2524 next_revision_data['build_time'] = run_results[4] | 2541 next_revision_data['build_time'] = run_results[4] |
| 2525 | 2542 |
| 2526 passed_regression = self._CheckIfRunPassed(run_results[0], | 2543 passed_regression = self._CheckIfRunPassed(run_results[0], |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3342 # bugs. If you change this, please update the perf dashboard as well. | 3359 # bugs. If you change this, please update the perf dashboard as well. |
| 3343 bisect_utils.OutputAnnotationStepStart('Results') | 3360 bisect_utils.OutputAnnotationStepStart('Results') |
| 3344 print 'Error: %s' % e.message | 3361 print 'Error: %s' % e.message |
| 3345 if opts.output_buildbot_annotations: | 3362 if opts.output_buildbot_annotations: |
| 3346 bisect_utils.OutputAnnotationStepClosed() | 3363 bisect_utils.OutputAnnotationStepClosed() |
| 3347 return 1 | 3364 return 1 |
| 3348 | 3365 |
| 3349 | 3366 |
| 3350 if __name__ == '__main__': | 3367 if __name__ == '__main__': |
| 3351 sys.exit(main()) | 3368 sys.exit(main()) |
| OLD | NEW |