summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsimonhatch@chromium.org <simonhatch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-21 17:20:04 +0000
committersimonhatch@chromium.org <simonhatch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-21 17:20:04 +0000
commit8997afddabf0efa3e867d50aaefa2b5f87eed08b (patch)
tree95df1961cbf6447d05f80d86a2289e301cbe0a1e
parentca2b80e9a1b578715eb85426585b7609c153e95f (diff)
downloadchromium_src-8997afddabf0efa3e867d50aaefa2b5f87eed08b.zip
chromium_src-8997afddabf0efa3e867d50aaefa2b5f87eed08b.tar.gz
chromium_src-8997afddabf0efa3e867d50aaefa2b5f87eed08b.tar.bz2
Added separate checkout and config file generation to bisect script.
BUG= NOTRY=true Review URL: https://chromiumcodereview.appspot.com/12261026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@183827 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--tools/PRESUBMIT.py48
-rwxr-xr-xtools/bisect-perf-regression.py140
-rw-r--r--tools/run-bisect-perf-regression.cfg41
-rwxr-xr-xtools/run-bisect-perf-regression.py100
4 files changed, 317 insertions, 12 deletions
diff --git a/tools/PRESUBMIT.py b/tools/PRESUBMIT.py
new file mode 100644
index 0000000..0157231
--- /dev/null
+++ b/tools/PRESUBMIT.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for bisect trybot.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+import imp
+
+def _ExamineBisectConfigFile(input_api, output_api):
+ for f in input_api.AffectedFiles():
+ if not f.LocalPath().endswith('run-bisect-perf-regression.cfg'):
+ continue
+
+ try:
+ cfg_file = imp.load_source('config', 'run-bisect-perf-regression.cfg')
+
+ for k, v in cfg_file.config.iteritems():
+ if v:
+ return f.LocalPath()
+ except (IOError, AttributeError, TypeError):
+ return f.LocalPath()
+
+ return None
+
+def _CheckNoChangesToBisectConfigFile(input_api, output_api):
+ results = _ExamineBisectConfigFile(input_api, output_api)
+ if results:
+ return [output_api.PresubmitError(
+ 'The bisection config file should only contain a config dict with '
+ 'empty fields. Changes to this file should never be submitted.',
+ items=[results])]
+
+ return []
+
+def CommonChecks(input_api, output_api):
+ results = []
+ results.extend(_CheckNoChangesToBisectConfigFile(input_api, output_api))
+ return results
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py
index 4afe1cf..fe1f19a 100755
--- a/tools/bisect-perf-regression.py
+++ b/tools/bisect-perf-regression.py
@@ -35,14 +35,14 @@ An example usage (using git hashes):
"""
-
-import re
-import os
+import errno
import imp
-import sys
-import shlex
import optparse
+import os
+import re
+import shlex
import subprocess
+import sys
# The additional repositories that might need to be bisected.
@@ -89,6 +89,25 @@ DEPOT_NAMES = DEPOT_DEPS_NAME.keys()
FILE_DEPS_GIT = '.DEPS.git'
+GCLIENT_SPEC = """
+solutions = [
+ { "name" : "src",
+ "url" : "https://chromium.googlesource.com/chromium/src.git",
+ "deps_file" : ".DEPS.git",
+ "managed" : True,
+ "custom_deps" : {
+ },
+ "safesync_url": "",
+ },
+ { "name" : "src-internal",
+ "url" : "ssh://gerrit-int.chromium.org:29419/" +
+ "chrome/src-internal.git",
+ "deps_file" : ".DEPS.git",
+ },
+]
+"""
+GCLIENT_SPEC = ''.join([l for l in GCLIENT_SPEC.splitlines()])
+
def IsStringFloat(string_to_check):
@@ -1134,6 +1153,84 @@ def DetermineAndCreateSourceControl():
return None
+def CreateAndChangeToSourceDirectory(working_directory):
+ """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If
+ the function is successful, the current working directory will change to that
+ of the new 'bisect' directory.
+
+ Returns:
+ True if the directory was successfully created (or already existed).
+ """
+ cwd = os.getcwd()
+ os.chdir(working_directory)
+ try:
+ os.mkdir('bisect')
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ return False
+ os.chdir('bisect')
+ return True
+
+
+def RunGClient(params):
+ """Runs gclient with the specified parameters.
+
+ Args:
+ params: A list of parameters to pass to gclient.
+
+ Returns:
+ The return code of the call.
+ """
+ cmd = ['gclient'] + params
+ return subprocess.call(cmd)
+
+
+def RunGClientAndCreateConfig():
+ """Runs gclient and creates a config containing both src and src-internal.
+
+ Returns:
+ The return code of the call.
+ """
+ return_code = RunGClient(
+ ['config', '--spec=%s' % GCLIENT_SPEC, '--git-deps'])
+ return return_code
+
+
+def RunGClientAndSync():
+ """Runs gclient and does a normal sync.
+
+ Returns:
+ The return code of the call.
+ """
+ return RunGClient(['sync'])
+
+
+def SetupGitDepot(output_buildbot_annotations):
+ """Sets up the depot for the bisection. The depot will be located in a
+ subdirectory called 'bisect'.
+
+ Returns:
+ True if gclient successfully created the config file and did a sync, False
+ otherwise.
+ """
+ name = 'Setting up Bisection Depot'
+
+ if output_buildbot_annotations:
+ OutputAnnotationStepStart(name)
+
+ passed = False
+
+ if not RunGClientAndCreateConfig():
+ if not RunGClientAndSync():
+ passed = True
+
+ if output_buildbot_annotations:
+ print
+ OutputAnnotationStepClosed()
+
+ return passed
+
+
def main():
usage = ('%prog [options] [-- chromium-options]\n'
@@ -1160,6 +1257,14 @@ def main():
type='str',
help='The desired metric to bisect on. For example ' +
'"vm_rss_final_b/vm_rss_f_b"')
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='Path to the working directory where the script will '
+ 'do an initial checkout of the chromium depot. The '
+ 'files will be placed in a subdirectory "bisect" under '
+ 'working_directory and that will be used to perform the '
+ 'bisection. This parameter is optional, if it is not '
+ 'supplied, the script will work from the current depot.')
parser.add_option('--use_goma',
action="store_true",
help='Add a bunch of extra threads for goma.')
@@ -1207,6 +1312,24 @@ def main():
print
return 1
+ metric_values = opts.metric.split('/')
+ if len(metric_values) != 2:
+ print "Invalid metric specified: [%s]" % (opts.metric,)
+ print
+ return 1
+
+ if opts.working_directory:
+ if not CreateAndChangeToSourceDirectory(opts.working_directory):
+ print 'Error: Could not create bisect directory.'
+ print
+ return 1
+
+ if not SetupGitDepot(opts.output_buildbot_annotations):
+ print 'Error: Failed to grab source.'
+ print
+ return 1
+
+ os.chdir(os.path.join(os.getcwd(), 'src'))
# Check what source control method they're using. Only support git workflow
# at the moment.
@@ -1223,13 +1346,6 @@ def main():
print
return 1
- metric_values = opts.metric.split('/')
- if len(metric_values) < 2:
- print "Invalid metric specified: [%s]" % (opts.metric,)
- print
- return 1
-
-
bisect_test = BisectPerformanceMetrics(source_control, opts)
bisect_results = bisect_test.Run(opts.command,
opts.bad_revision,
diff --git a/tools/run-bisect-perf-regression.cfg b/tools/run-bisect-perf-regression.cfg
new file mode 100644
index 0000000..0cf4b5c
--- /dev/null
+++ b/tools/run-bisect-perf-regression.cfg
@@ -0,0 +1,41 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Config file for Run Performance Test Bisect Tool
+
+This script is intended for use by anyone that wants to run a remote bisection
+on a range of revisions to look for a performance regression. Modify the config
+below and add the revision range, performance command, and metric. You can then
+run a git try <bot>.
+
+Changes to this file should never be submitted.
+
+Args:
+ 'command': This is the full command line to pass to the
+ bisect-perf-regression.py script in order to execute the test.
+ 'good_revision': An svn or git revision where the metric hadn't regressed yet.
+ 'bad_revision': An svn or git revision sometime after the metric had
+ regressed.
+ 'metric': The name of the metric to parse out from the results of the
+ performance test.
+
+
+Sample config:
+
+config = {
+ 'command': './out/Release/performance_ui_tests' +
+ ' --gtest_filter=PageCyclerTest.Intl1File',
+ 'good_revision': '179755',
+ 'bad_revision': '179782',
+ 'metric': 'times/t'
+}
+
+"""
+
+config = {
+ 'command': '',
+ 'good_revision': '',
+ 'bad_revision': '',
+ 'metric': '',
+}
diff --git a/tools/run-bisect-perf-regression.py b/tools/run-bisect-perf-regression.py
new file mode 100755
index 0000000..120e407
--- /dev/null
+++ b/tools/run-bisect-perf-regression.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Run Performance Test Bisect Tool
+
+This script is used by a trybot to run the src/tools/bisect-perf-regression.py
+script with the parameters specified in run-bisect-perf-regression.cfg. It will
+check out a copy of the depot in a subdirectory 'bisect' of the working
+directory provided, and run the bisect-perf-regression.py script there.
+
+"""
+
+import imp
+import optparse
+import os
+import subprocess
+import sys
+
+
+def LoadConfigFile():
+ """Attempts to load the file 'run-bisect-perf-regression.cfg' as a module
+ and grab the global config dict.
+
+ Returns:
+ The config dict which should be formatted as follows:
+ {'command': string, 'good_revision': string, 'bad_revision': string
+ 'metric': string}.
+ Returns None on failure.
+ """
+ try:
+ local_vars = {}
+ execfile('run-bisect-perf-regression.cfg', local_vars)
+
+ return local_vars['config']
+ except:
+ return None
+
+
+def RunBisectionScript(config, working_directory):
+ """Attempts to execute src/tools/bisect-perf-regression.py with the parameters
+ passed in.
+
+ Args:
+ config: A dict containing the parameters to pass to the script.
+
+ Returns:
+ 0 on success, otherwise 1.
+ """
+
+ cmd = ['python', 'bisect-perf-regression.py',
+ '-c', config['command'],
+ '-g', config['good_revision'],
+ '-b', config['bad_revision'],
+ '-m', config['metric'],
+ '--working_directory', working_directory,
+ '--output_buildbot_annotations']
+
+ return_code = subprocess.call(cmd)
+
+ if return_code:
+ print 'Error: bisect-perf-regression.py returned with error %d' %\
+ return_code
+ print
+
+ return return_code
+
+
+def main():
+
+ usage = ('%prog [options] [-- chromium-options]\n'
+ 'Used by a trybot to run the bisection script using the parameters'
+ ' provided in the run-bisect-perf-regression.cfg file.')
+
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='A working directory to supply to the bisection '
+ 'script, which will use it as the location to checkout '
+ 'a copy of the chromium depot.')
+ (opts, args) = parser.parse_args()
+
+ if not opts.working_directory:
+ print 'Error: missing required parameter: --working_directory'
+ print
+ parser.print_help()
+ return 1
+
+ config = LoadConfigFile()
+ if not config:
+ print 'Error: Could not load config file.'
+ print
+ return 1
+
+ return RunBisectionScript(config, opts.working_directory)
+
+
+if __name__ == '__main__':
+ sys.exit(main())