summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsimonhatch@chromium.org <simonhatch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 19:29:50 +0000
committersimonhatch@chromium.org <simonhatch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-15 19:29:50 +0000
commit2deb10df4b5547e74f4ff89652421f7ab780f018 (patch)
tree527f63ab984f058e8722f3811c75d202a09fb5b5
parent7bfc16ace99007fd1f2d75096651110be691c693 (diff)
downloadchromium_src-2deb10df4b5547e74f4ff89652421f7ab780f018.zip
chromium_src-2deb10df4b5547e74f4ff89652421f7ab780f018.tar.gz
chromium_src-2deb10df4b5547e74f4ff89652421f7ab780f018.tar.bz2
Added windows support for bisect script. Added build_preference parameter to bisect script to specify build system.
BUG= NOTRY=true Review URL: https://chromiumcodereview.appspot.com/12712009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188451 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-xtools/bisect-perf-regression.py227
-rw-r--r--tools/bisect_utils.py10
-rw-r--r--tools/run-bisect-perf-regression.cfg19
-rwxr-xr-xtools/run-bisect-perf-regression.py7
4 files changed, 216 insertions, 47 deletions
diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py
index 0776836..27ad54a 100755
--- a/tools/bisect-perf-regression.py
+++ b/tools/bisect-perf-regression.py
@@ -35,6 +35,7 @@ An example usage (using git hashes):
"""
+import errno
import imp
import math
import optparse
@@ -175,6 +176,15 @@ def IsStringInt(string_to_check):
return False
+def IsWindows():
+ """Checks whether or not the script is running on Windows.
+
+ Returns:
+ True if running on Windows.
+ """
+ return os.name == 'nt'
+
+
def RunProcess(command, print_output=False):
"""Run an arbitrary command, returning its output and return code.
@@ -186,8 +196,11 @@ def RunProcess(command, print_output=False):
Returns:
A tuple of the output and return code.
"""
+ if print_output:
+ print 'Running: [%s]' % ' '.join(command)
+
# On Windows, use shell=True to get PATH interpretation.
- shell = (os.name == 'nt')
+ shell = IsWindows()
proc = subprocess.Popen(command,
shell=shell,
stdout=subprocess.PIPE,
@@ -227,6 +240,37 @@ def RunGit(command):
return RunProcess(command)
+def BuildWithMake(threads, targets, print_output):
+ cmd = ['make', 'BUILDTYPE=Release', '-j%d' % threads] + targets
+
+ (output, return_code) = RunProcess(cmd, print_output)
+
+ return not return_code
+
+
+def BuildWithNinja(threads, targets, print_output):
+ cmd = ['ninja', '-C', os.path.join('out', 'Release'),
+ '-j%d' % threads] + targets
+
+ (output, return_code) = RunProcess(cmd, print_output)
+
+ return not return_code
+
+
+def BuildWithVisualStudio(targets, print_output):
+ path_to_devenv = os.path.abspath(
+ os.path.join(os.environ['VS100COMNTOOLS'], '..', 'IDE', 'devenv.com'))
+ path_to_sln = os.path.join(os.getcwd(), 'chrome', 'chrome.sln')
+ cmd = [path_to_devenv, '/build', 'Release', path_to_sln]
+
+ for t in targets:
+ cmd.extend(['/Project', t])
+
+ (output, return_code) = RunProcess(cmd, print_output)
+
+ return not return_code
+
+
class SourceControl(object):
"""SourceControl is an abstraction over the underlying source control
system used for chromium. For now only git is supported, but in the
@@ -243,11 +287,9 @@ class SourceControl(object):
revision: The git SHA1 or svn CL (depending on workflow).
Returns:
- A tuple of the output and return code.
+ The return code of the call.
"""
- args = ['gclient', 'sync', '--revision', revision]
-
- return RunProcess(args)
+ return bisect_utils.RunGClient(['sync', '--revision', revision])
class GitSourceControl(SourceControl):
@@ -297,9 +339,9 @@ class GitSourceControl(SourceControl):
if use_gclient:
results = self.SyncToRevisionWithGClient(revision)
else:
- results = RunGit(['checkout', revision])
+ results = RunGit(['checkout', revision])[1]
- return not results[1]
+ return not results
def ResolveToRevision(self, revision_to_check, depot, search):
"""If an SVN revision is supplied, try to resolve it to a git SHA1.
@@ -500,40 +542,35 @@ class BisectPerformanceMetrics(object):
Returns:
True if the build was successful.
"""
-
if self.opts.debug_ignore_build:
return True
- gyp_var = os.getenv('GYP_GENERATORS')
-
- num_threads = 16
-
+ targets = ['chrome', 'performance_ui_tests']
+ threads = 16
if self.opts.use_goma:
- num_threads = 100
-
- if gyp_var != None and 'ninja' in gyp_var:
- args = ['ninja',
- '-C',
- 'out/Release',
- '-j%d' % num_threads,
- 'chrome',
- 'performance_ui_tests']
- else:
- args = ['make',
- 'BUILDTYPE=Release',
- '-j%d' % num_threads,
- 'chrome',
- 'performance_ui_tests']
+ threads = 300
cwd = os.getcwd()
os.chdir(self.src_cwd)
- (output, return_code) = RunProcess(args,
- self.opts.output_buildbot_annotations)
+ if self.opts.build_preference == 'make':
+ build_success = BuildWithMake(threads, targets,
+ self.opts.output_buildbot_annotations)
+ elif self.opts.build_preference == 'ninja':
+ if IsWindows():
+ targets = [t + '.exe' for t in targets]
+ build_success = BuildWithNinja(threads, targets,
+ self.opts.output_buildbot_annotations)
+ elif self.opts.build_preference == 'msvs':
+ assert IsWindows(), 'msvs is only supported on Windows.'
+ build_success = BuildWithVisualStudio(targets,
+ self.opts.output_buildbot_annotations)
+ else:
+ assert False, 'No build system defined.'
os.chdir(cwd)
- return not return_code
+ return build_success
def RunGClientHooks(self):
"""Runs gclient with runhooks command.
@@ -545,9 +582,7 @@ class BisectPerformanceMetrics(object):
if self.opts.debug_ignore_build:
return True
- results = RunProcess(['gclient', 'runhooks'])
-
- return not results[1]
+ return not bisect_utils.RunGClient(['runhooks'])
def ParseMetricValuesFromOutput(self, metric, text):
"""Parses output from performance_ui_tests and retrieves the results for
@@ -644,6 +679,9 @@ class BisectPerformanceMetrics(object):
if self.opts.debug_ignore_perf_test:
return ({'debug' : 0.0}, 0)
+ if IsWindows():
+ command_to_run = command_to_run.replace('/', r'\\')
+
args = shlex.split(command_to_run)
cwd = os.getcwd()
@@ -735,10 +773,11 @@ class BisectPerformanceMetrics(object):
# Having these pyc files around between runs can confuse the
# perf tests and cause them to crash.
- cmd = ['find', '.', '-name', '*.pyc', '-exec', 'rm', '-f', '{}', ';']
- (output, return_code) = RunProcess(cmd)
-
- assert not output, "Cleaning *.pyc failed."
+ for (path, dir, files) in os.walk(os.getcwd()):
+ for cur_file in files:
+ if cur_file.endswith('.pyc'):
+ path_to_file = os.path.join(path, cur_file)
+ os.remove(path_to_file)
def SyncBuildAndRunRevision(self, revision, depot, command_to_run, metric):
"""Performs a full sync/build/run of the specified revision.
@@ -1311,6 +1350,100 @@ def DetermineAndCreateSourceControl():
return None
+def SetNinjaBuildSystemDefault():
+ """Makes ninja the default build system to be used by
+ the bisection script."""
+ gyp_var = os.getenv('GYP_GENERATORS')
+
+ if not gyp_var or not 'ninja' in gyp_var:
+ if gyp_var:
+ os.environ['GYP_GENERATORS'] = gyp_var + ',ninja'
+ else:
+ os.environ['GYP_GENERATORS'] = 'ninja'
+
+ if IsWindows():
+ os.environ['GYP_DEFINES'] = 'component=shared_library '\
+ 'incremental_chrome_dll=1 disable_nacl=1 fastbuild=1 '\
+ 'chromium_win_pch=0'
+
+
+def CheckPlatformSupported(opts):
+ """Checks that this platform and build system are supported.
+
+ Args:
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if the platform and build system are supported.
+ """
+ # Haven't tested the script out on any other platforms yet.
+ supported = ['posix', 'nt']
+ if not os.name in supported:
+ print "Sorry, this platform isn't supported yet."
+ print
+ return False
+
+ if IsWindows():
+ if not opts.build_preference:
+ opts.build_preference = 'msvs'
+
+ if opts.build_preference == 'msvs':
+ if not os.getenv('VS100COMNTOOLS'):
+ print 'Error: Path to visual studio could not be determined.'
+ print
+ return False
+ elif opts.build_preference == 'ninja':
+ SetNinjaBuildSystemDefault()
+ else:
+ assert False, 'Error: %s build not supported' % opts.build_preference
+ else:
+ if not opts.build_preference:
+ opts.build_preference = 'make'
+
+ if opts.build_preference == 'ninja':
+ SetNinjaBuildSystemDefault()
+ elif opts.build_preference != 'make':
+ assert False, 'Error: %s build not supported' % opts.build_preference
+
+ bisect_utils.RunGClient(['runhooks'])
+
+ return True
+
+
+def RmTreeAndMkDir(path_to_dir):
+ """Removes the directory tree specified, and then creates an empty
+ directory in the same location.
+
+ Args:
+ path_to_dir: Path to the directory tree.
+
+ Returns:
+ True if successful, False if an error occurred.
+ """
+ try:
+ if os.path.exists(path_to_dir):
+ shutil.rmtree(path_to_dir)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ return False
+
+ try:
+ os.mkdir(path_to_dir)
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ return False
+
+ return True
+
+
+def RemoveBuildFiles():
+ """Removes build files from previous runs."""
+ if RmTreeAndMkDir(os.path.join('out', 'Release')):
+ if RmTreeAndMkDir(os.path.join('build', 'Release')):
+ return True
+ return False
+
+
def main():
usage = ('%prog [options] [-- chromium-options]\n'
@@ -1358,6 +1491,12 @@ def main():
'truncated mean. Values will be clamped to range [0, 25]. '
'Default value is 10 (highest/lowest 10% will be '
'discarded).')
+ parser.add_option('--build_preference',
+ type='choice',
+ choices=['msvs', 'ninja', 'make'],
+ help='The preferred build system to use. On linux/mac '
+ 'the options are make/ninja. On Windows, the options '
+ 'are msvs/ninja.')
parser.add_option('--use_goma',
action="store_true",
help='Add a bunch of extra threads for goma.')
@@ -1403,12 +1542,6 @@ def main():
opts.truncate_percent = min(max(opts.truncate_percent, 0), 25)
opts.truncate_percent = opts.truncate_percent / 100.0
- # Haven't tested the script out on any other platforms yet.
- if not os.name in ['posix']:
- print "Sorry, this platform isn't supported yet."
- print
- return 1
-
metric_values = opts.metric.split('/')
if len(metric_values) != 2:
print "Invalid metric specified: [%s]" % (opts.metric,)
@@ -1421,6 +1554,14 @@ def main():
os.chdir(os.path.join(os.getcwd(), 'src'))
+ if not RemoveBuildFiles():
+ print "Something went wrong removing the build files."
+ print
+ return 1
+
+ if not CheckPlatformSupported(opts):
+ return 1
+
# Check what source control method they're using. Only support git workflow
# at the moment.
source_control = DetermineAndCreateSourceControl()
diff --git a/tools/bisect_utils.py b/tools/bisect_utils.py
index 353867d..0439d76 100644
--- a/tools/bisect_utils.py
+++ b/tools/bisect_utils.py
@@ -28,6 +28,7 @@ solutions = [
},
]
"""
+GCLIENT_SPEC = ''.join([l for l in GCLIENT_SPEC.splitlines()])
def OutputAnnotationStepStart(name):
@@ -76,8 +77,15 @@ def RunGClient(params):
Returns:
The return code of the call.
"""
+ if os.name == 'nt':
+ # "HOME" isn't normally defined on windows, but is needed
+ # for git to find the user's .netrc file.
+ if not os.getenv('HOME'):
+ os.environ['HOME'] = os.environ['USERPROFILE']
+
+ shell = os.name == 'nt'
cmd = ['gclient'] + params
- return subprocess.call(cmd)
+ return subprocess.call(cmd, shell=shell)
def RunGClientAndCreateConfig():
diff --git a/tools/run-bisect-perf-regression.cfg b/tools/run-bisect-perf-regression.cfg
index ea39f5e..792083c 100644
--- a/tools/run-bisect-perf-regression.cfg
+++ b/tools/run-bisect-perf-regression.cfg
@@ -22,7 +22,6 @@ Args:
'repeat_count': The number of times to repeat the performance test.
'truncate_percent': Discard the highest/lowest % values from performance test.
-
Sample config:
config = {
@@ -32,7 +31,21 @@ config = {
'bad_revision': '179782',
'metric': 'times/t',
'repeat_count': '10',
- 'truncate_percent': 10,
+ 'truncate_percent': '10',
+}
+
+On Windows:
+ - If you're calling a python script you will need to add "python" to
+the command:
+
+config = {
+ 'command': 'python tools/perf/run_multipage_benchmarks -v --browser=release'\
+ ' kraken tools/perf/page_sets/kraken.json',
+ 'good_revision': '185319',
+ 'bad_revision': '185364',
+ 'metric': 'Total/Total',
+ 'repeat_count': '10',
+ 'truncate_percent': '10',
}
"""
@@ -43,5 +56,5 @@ config = {
'bad_revision': '',
'metric': '',
'repeat_count':'',
- 'truncate_percent':''
+ 'truncate_percent':'',
}
diff --git a/tools/run-bisect-perf-regression.py b/tools/run-bisect-perf-regression.py
index 8807942..306b345 100755
--- a/tools/run-bisect-perf-regression.py
+++ b/tools/run-bisect-perf-regression.py
@@ -72,6 +72,11 @@ def RunBisectionScript(config, working_directory, path_to_file, path_to_goma):
if config['truncate_percent']:
cmd.extend(['-t', config['truncate_percent']])
+ if os.name == 'nt':
+ cmd.extend(['--build_preference', 'ninja'])
+ else:
+ cmd.extend(['--build_preference', 'make'])
+
goma_file = ''
if path_to_goma:
path_to_goma = os.path.abspath(path_to_goma)
@@ -92,6 +97,8 @@ def RunBisectionScript(config, working_directory, path_to_file, path_to_goma):
print
return return_code
+ cmd = [str(c) for c in cmd]
+
return_code = subprocess.call(cmd)
if path_to_goma: