Index: tools/bisect-perf-regression.py
|
diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py
|
index 12e07d612112d93c8c03dc9e6bd3df64a8986c41..95ea93d38ab3bdf7972468d9ba942de5ea2ed831 100755
|
--- a/tools/bisect-perf-regression.py
|
+++ b/tools/bisect-perf-regression.py
|
@@ -152,7 +152,7 @@ DEPOT_NAMES = DEPOT_DEPS_NAME.keys()
|
|
CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome'
|
|
-# Possible return values from BisectPerformanceMetrics.SyncBuildAndRunRevision.
|
+# Possible return values from BisectPerformanceMetrics.RunTest.
|
BUILD_RESULT_SUCCEED = 0
|
BUILD_RESULT_FAIL = 1
|
BUILD_RESULT_SKIPPED = 2
|
@@ -1187,7 +1187,7 @@ class BisectPerformanceMetrics(object):
|
|
return results
|
|
- def BackupOrRestoreOutputdirectory(self, restore=False, build_type='Release'):
|
+ def BackupOrRestoreOutputDirectory(self, restore=False, build_type='Release'):
|
"""Backs up or restores build output directory based on restore argument.
|
|
Args:
|
@@ -1285,7 +1285,7 @@ class BisectPerformanceMetrics(object):
|
# Unzip build archive directory.
|
try:
|
RmTreeAndMkDir(output_dir, skip_makedir=True)
|
- self.BackupOrRestoreOutputdirectory(restore=False)
|
+ self.BackupOrRestoreOutputDirectory(restore=False)
|
# Build output directory based on target(e.g. out/Release, out/Debug).
|
target_build_output_dir = os.path.join(abs_build_dir, build_type)
|
ExtractZip(downloaded_file, abs_build_dir)
|
@@ -1303,7 +1303,7 @@ class BisectPerformanceMetrics(object):
|
return True
|
except Exception as e:
|
print 'Something went wrong while extracting archive file: %s' % e
|
- self.BackupOrRestoreOutputdirectory(restore=True)
|
+ self.BackupOrRestoreOutputDirectory(restore=True)
|
# Cleanup any leftovers from unzipping.
|
if os.path.exists(output_dir):
|
RmTreeAndMkDir(output_dir, skip_makedir=True)
|
@@ -1711,7 +1711,7 @@ class BisectPerformanceMetrics(object):
|
print
|
return (values, success_code, output_of_all_runs)
|
|
- def FindAllRevisionsToSync(self, revision, depot):
|
+ def _FindAllRevisionsToSync(self, revision, depot):
|
"""Finds all dependent revisions and depots that need to be synced.
|
|
For example skia is broken up into 3 git mirrors over skia/src,
|
@@ -1799,9 +1799,12 @@ class BisectPerformanceMetrics(object):
|
os.chdir(cwd)
|
return not return_code
|
|
- def PerformPreSyncCleanup(self, revision, depot):
|
+ def _PerformPreSyncCleanup(self, depot):
|
"""Performs any necessary cleanup before syncing.
|
|
+ Args:
|
+ depot: Depot name.
|
+
|
Returns:
|
True if successful.
|
"""
|
@@ -1819,9 +1822,12 @@ class BisectPerformanceMetrics(object):
|
return self.PerformCrosChrootCleanup()
|
return True
|
|
- def RunPostSync(self, depot):
|
+ def _RunPostSync(self, depot):
|
"""Performs any work after syncing.
|
|
+ Args:
|
+ depot: Depot name.
|
+
|
Returns:
|
True if successful.
|
"""
|
@@ -1861,96 +1867,110 @@ class BisectPerformanceMetrics(object):
|
|
return False
|
|
- def SyncBuildAndRunRevision(self, revision, depot, command_to_run, metric,
|
- skippable=False):
|
+ def RunTest(self, revision, depot, command, metric, skippable=False):
|
"""Performs a full sync/build/run of the specified revision.
|
|
Args:
|
revision: The revision to sync to.
|
depot: The depot that's being used at the moment (src, webkit, etc.)
|
- command_to_run: The command to execute the performance test.
|
+ command: The command to execute the performance test.
|
metric: The performance metric being tested.
|
|
Returns:
|
On success, a tuple containing the results of the performance test.
|
Otherwise, a tuple with the error message.
|
"""
|
+ # Decide which sync program to use.
|
sync_client = None
|
if depot == 'chromium' or depot == 'android-chrome':
|
sync_client = 'gclient'
|
elif depot == 'cros':
|
sync_client = 'repo'
|
|
- revisions_to_sync = self.FindAllRevisionsToSync(revision, depot)
|
-
|
+ # Decide what depots will need to be synced to what revisions.
|
+ revisions_to_sync = self._FindAllRevisionsToSync(revision, depot)
|
if not revisions_to_sync:
|
return ('Failed to resolve dependent depots.', BUILD_RESULT_FAIL)
|
|
- if not self.PerformPreSyncCleanup(revision, depot):
|
+ if not self._PerformPreSyncCleanup(depot):
|
return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL)
|
|
- success = True
|
-
|
+ # Do the syncing for all depots.
|
if not self.opts.debug_ignore_sync:
|
- for r in revisions_to_sync:
|
- self.ChangeToDepotWorkingDirectory(r[0])
|
-
|
- if sync_client:
|
- self.PerformPreBuildCleanup()
|
-
|
- # If you're using gclient to sync, you need to specify the depot you
|
- # want so that all the dependencies sync properly as well.
|
- # i.e. gclient sync src@<SHA1>
|
- current_revision = r[1]
|
- if sync_client == 'gclient':
|
- current_revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'],
|
- current_revision)
|
- if not self.source_control.SyncToRevision(current_revision,
|
- sync_client):
|
- success = False
|
+ if not self._SyncAllRevisions(revisions_to_sync, sync_client):
|
+ return ('Failed to sync: [%s]' % str(revision), BUILD_RESULT_FAIL)
|
+
|
+ # Try to do any post-sync steps. This may include "gclient runhooks".
|
+ if not self._RunPostSync(depot):
|
+ return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL)
|
+
|
+ # Skip this revision if it can be skipped.
|
+ if skippable and self.ShouldSkipRevision(depot, revision):
|
+ return ('Skipped revision: [%s]' % str(revision),
|
+ BUILD_RESULT_SKIPPED)
|
+
|
+ # Obtain a build for this revision. This may be done by requesting a build
|
+ # from another builder, waiting for it and downloading it.
|
+ start_build_time = time.time()
|
+ build_success = self.BuildCurrentRevision(depot, revision)
|
+ if not build_success:
|
+ return ('Failed to build revision: [%s]' % str(revision),
|
+ BUILD_RESULT_FAIL)
|
+ after_build_time = time.time()
|
|
- break
|
+ # Possibly alter the command.
|
+ command = self.GetCompatibleCommand(command, revision, depot)
|
|
- if success:
|
- success = self.RunPostSync(depot)
|
- if success:
|
- if skippable and self.ShouldSkipRevision(depot, revision):
|
- return ('Skipped revision: [%s]' % str(revision),
|
- BUILD_RESULT_SKIPPED)
|
-
|
- start_build_time = time.time()
|
- if self.BuildCurrentRevision(depot, revision):
|
- after_build_time = time.time()
|
- # Hack to support things that got changed.
|
- command_to_run = self.GetCompatibleCommand(
|
- command_to_run, revision, depot)
|
- results = self.RunPerformanceTestAndParseResults(command_to_run,
|
- metric)
|
- # Restore build output directory once the tests are done, to avoid
|
- # any discrepancies.
|
- if self.IsDownloadable(depot) and revision:
|
- self.BackupOrRestoreOutputdirectory(restore=True)
|
-
|
- if results[1] == 0:
|
- external_revisions = self._Get3rdPartyRevisions(depot)
|
-
|
- if not external_revisions is None:
|
- return (results[0], results[1], external_revisions,
|
- time.time() - after_build_time, after_build_time -
|
- start_build_time)
|
- else:
|
- return ('Failed to parse DEPS file for external revisions.',
|
- BUILD_RESULT_FAIL)
|
- else:
|
- return results
|
- else:
|
- return ('Failed to build revision: [%s]' % str(revision),
|
- BUILD_RESULT_FAIL)
|
- else:
|
- return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL)
|
+ # Run the command and get the results.
|
+ results = self.RunPerformanceTestAndParseResults(command, metric)
|
+
|
+ # Restore build output directory once the tests are done, to avoid
|
+ # any discrepancies.
|
+ if self.IsDownloadable(depot) and revision:
|
+ self.BackupOrRestoreOutputDirectory(restore=True)
|
+
|
+ # A value other than 0 indicates that the test couldn't be run, and results
|
+ # should also include an error message.
|
+ if results[1] != 0:
|
+ return results
|
+
|
+ external_revisions = self._Get3rdPartyRevisions(depot)
|
+
|
+ if not external_revisions is None:
|
+ return (results[0], results[1], external_revisions,
|
+ time.time() - after_build_time, after_build_time -
|
+ start_build_time)
|
else:
|
- return ('Failed to sync revision: [%s]' % str(revision),
|
- BUILD_RESULT_FAIL)
|
+ return ('Failed to parse DEPS file for external revisions.',
|
+ BUILD_RESULT_FAIL)
|
+
|
+ def _SyncAllRevisions(self, revisions_to_sync, sync_client):
|
+ """Syncs multiple depots to particular revisions.
|
+
|
+ Args:
|
+ revisions_to_sync: A list of (depot, revision) pairs to be synced.
|
+ sync_client: Program used to sync, e.g. "gclient", "repo". Can be None.
|
+
|
+ Returns:
|
+ True if successful, False otherwise.
|
+ """
|
+ for depot, revision in revisions_to_sync:
|
+ self.ChangeToDepotWorkingDirectory(depot)
|
+
|
+ if sync_client:
|
+ self.PerformPreBuildCleanup()
|
+
|
+ # When using gclient to sync, you need to specify the depot you
|
+ # want so that all the dependencies sync properly as well.
|
+ # i.e. gclient sync src@<SHA1>
|
+ if sync_client == 'gclient':
|
+ revision = '%s@%s' % (DEPOT_DEPS_NAME[depot]['src'], revision)
|
+
|
+ sync_success = self.source_control.SyncToRevision(revision, sync_client)
|
+ if not sync_success:
|
+ return False
|
+
|
+ return True
|
|
def _CheckIfRunPassed(self, current_value, known_good_value, known_bad_value):
|
"""Given known good and bad values, decide if the current_value passed
|
@@ -2119,14 +2139,12 @@ class BisectPerformanceMetrics(object):
|
Returns:
|
A tuple with the results of building and running each revision.
|
"""
|
- bad_run_results = self.SyncBuildAndRunRevision(
|
- bad_rev, target_depot, cmd, metric)
|
+ bad_run_results = self.RunTest(bad_rev, target_depot, cmd, metric)
|
|
good_run_results = None
|
|
if not bad_run_results[1]:
|
- good_run_results = self.SyncBuildAndRunRevision(
|
- good_rev, target_depot, cmd, metric)
|
+ good_run_results = self.RunTest(good_rev, target_depot, cmd, metric)
|
|
return (bad_run_results, good_run_results)
|
|
@@ -2510,10 +2528,9 @@ class BisectPerformanceMetrics(object):
|
|
print 'Working on revision: [%s]' % next_revision_id
|
|
- run_results = self.SyncBuildAndRunRevision(next_revision_id,
|
- next_revision_depot,
|
- command_to_run,
|
- metric, skippable=True)
|
+ run_results = self.RunTest(
|
+ next_revision_id, next_revision_depot, command_to_run, metric,
|
+ skippable=True)
|
|
# If the build is successful, check whether or not the metric
|
# had regressed.
|
|