blob: 09b3a241d28e16f18d54f5aba6f8aeec44aafa02 [file] [log] [blame]
# Copyright 2014 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.
from recipe_engine import recipe_api
class PGOApi(recipe_api.RecipeApi):
"""
PGOApi encapsulate the various step involved in a PGO build.
"""
def __init__(self, **kwargs):
super(PGOApi, self).__init__(**kwargs)
def _compile_instrumented_image(self, bot_config, mb_config_path=None):
"""
Generates the instrumented version of the binaries.
"""
self.m.chromium.set_config(bot_config['chromium_config_instrument'],
**bot_config.get('chromium_config_kwargs'))
self.m.chromium.runhooks(name='Runhooks: Instrumentation phase.')
self.m.chromium.run_mb(
self.m.properties['mastername'],
self.m.properties['buildername'],
mb_config_path=mb_config_path,
use_goma=False,
phase=1)
# Remove the profile files from the previous builds.
self.m.file.rmglob(
'remove previous profiles', self.m.chromium.output_dir, '*.pg[cd]')
self.m.chromium.compile(name='Compile: Instrumentation phase.')
def _run_pgo_benchmarks(self):
"""
Run a suite of telemetry benchmarks to generate some profiling data.
"""
target_arch = self.m.chromium.c.gyp_env.GYP_DEFINES['target_arch']
target_cpu = {'ia32': 'x86'}.get(target_arch) or target_arch
args = [
'--browser-type', self.m.chromium.c.build_config_fs.lower(),
'--target-cpu', target_cpu,
'--build-dir', self.m.chromium.output_dir,
]
self.m.python(
'Profiling benchmarks.',
self.m.path['checkout'].join('build', 'win',
'run_pgo_profiling_benchmarks.py'),
args)
def _compile_optimized_image(self, bot_config, mb_config_path=None):
"""
Generates the optimized version of the binaries.
"""
self.m.chromium.set_config(bot_config['chromium_config_optimize'],
**bot_config.get('chromium_config_kwargs'))
self.m.chromium.runhooks(name='Runhooks: Optimization phase.')
self.m.chromium.run_mb(
self.m.properties['mastername'],
self.m.properties['buildername'],
mb_config_path=mb_config_path,
use_goma=False,
phase=2)
self.m.chromium.compile(name='Compile: Optimization phase.')
def _merge_pgc_files(self):
"""
Calls the script responsible of merging the PGC files.
If this script is missing then this will be done automatically by the
compiler during the final compile step.
"""
merge_script = self.m.path['checkout'].join('build', 'win',
'merge_pgc_files.py')
if not self.m.path.exists(merge_script):
return
target_arch = self.m.chromium.c.gyp_env.GYP_DEFINES['target_arch']
target_cpu = {'ia32': 'x86'}.get(target_arch) or target_arch
base_args = [
'--checkout-dir', self.m.path['checkout'],
'--target-cpu', target_cpu,
'--build-dir', self.m.chromium.output_dir,
]
for f in self.m.file.glob_paths('list PGD files',
self.m.chromium.output_dir, '*.pgd',
test_data=['test1.pgd', 'test2.pgd']):
binary_name = self.m.path.splitext(self.m.path.basename(f))[0]
args = base_args + ['--binary-name', binary_name]
self.m.python('Merge the pgc files for %s.' % binary_name,
merge_script, args)
self.m.file.rmglob('remove pgc files', self.m.chromium.output_dir,
'%s!*.pgc' % binary_name)
def compile_pgo(self, bot_config):
"""
Do a PGO build. This takes care of building an instrumented image, profiling
it and then compiling the optimized version of it.
"""
self.m.gclient.set_config(bot_config['gclient_config'])
# Augment the DEPS path if needed.
if '%s' in self.m.gclient.c.solutions[0].deps_file: # pragma: no cover
self.m.gclient.c.solutions[0].deps_file = (
self.m.gclient.c.solutions[0].deps_file % bot_config['bucket'])
if self.m.properties.get('bot_id') != 'fake_slave':
self.m.chromium.taskkill()
update_step = self.m.bot_update.ensure_checkout()
if bot_config.get('patch_root'):
self.m.path['checkout'] = self.m.path['start_dir'].join(
bot_config.get('patch_root'))
# First step: compilation of the instrumented build.
self._compile_instrumented_image(bot_config)
# Second step: profiling of the instrumented build.
self._run_pgo_benchmarks()
# Merge the pgc files.
self._merge_pgc_files()
if bot_config.get('archive_pgd', False):
self.archive_profile_database(
update_step.presentation.properties['got_revision'])
step_result = self.m.step.active_result
step_result.presentation.status = self.m.step.WARNING
# Third step: Compilation of the optimized build, this will use the
# profile data files produced by the previous step.
self._compile_optimized_image(bot_config)
def archive_profile_database(self, revision):
"""
Archive the profile database into a cloud bucket and use 'git notes' to
annotate the current commit with the URL to this file.
"""
# Temporarily turn any failure during this step into a warning until the
# permissions issues have been fixed.
# TODO(sebmarchand): Remove the try/except once it works.
try:
with self.m.step.nest("archive profile database"):
assert self.m.platform.is_win
self.m.cipd.set_service_account_credentials(
"C:\\creds\\service_accounts\\service-account-pgo-bot.json")
target_arch = {
'ia32': '386',
'x64': 'amd64',
}[self.m.chromium.c.gyp_env.GYP_DEFINES['target_arch']]
package_name = "chromium/pgo/profiles/profile_database/windows-%s" % (
target_arch)
pkg = self.m.cipd.PackageDefinition(package_name,
self.m.chromium.output_dir,
'copy')
# Copy the pgd files in a temp directory so cipd can pick them up.
for f in self.m.file.glob_paths('list PGD files',
self.m.chromium.output_dir, '*.pgd',
test_data=['test.pgd']):
pkg.add_file(f)
pkg_json = self.m.cipd.create_from_pkg(pkg)
instance_id = pkg_json['instance_id']
# Add the git notes for this profile database.
git_notes_ref = ('refs/notes/pgo/profile_database/windows-%s' %
target_arch)
git_config = {
'user.email': 'pgo-bot@chromium.org',
'user.name': 'PGO bot'
}
self.m.git('fetch', '-f',
'https://chromium.googlesource.com/chromium/src.git',
'%s:%s' % (git_notes_ref, git_notes_ref))
self.m.git('notes', '--ref', git_notes_ref,
'add', '-m', instance_id, revision,
git_config_options=git_config)
self.m.git('push', 'https://chromium.googlesource.com/chromium/src.git',
git_notes_ref)
except self.m.step.StepFailure:
step_result = self.m.step.active_result
step_result.presentation.status = self.m.step.WARNING