Bug 1580028 - Always merge PGO profile data in the run task; r=firefox-build-system-reviewers,chmanchester

If the run task generates bad profile data, the merge step in the
profile-use task will fail. However, retrying the profile-use task
doesn't fix the problem, and there isn't a straightforward way to retry
the run task in this situation. Instead we can add a clang toolchain to
all the run tasks, and perform the merge there.

This means the output from the run task will always be a successfully
merged file called 'merged.profdata', and we no longer need to perform
the merge as part of the profile-use build as a GENERATED_FILES step.

Depends on D45262

Differential Revision: https://phabricator.services.mozilla.com/D45263

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mike Shal 2019-09-10 21:56:15 +00:00
parent 93f80b9e53
commit 3b8df1c395
11 changed files with 47 additions and 53 deletions

View file

@ -1,18 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import glob
import subprocess
import sys
import buildconfig
def main(_, profile_dir):
profraw_files = glob.glob(profile_dir + '/*.profraw')
if not profraw_files:
print('Could not find any profraw files in ' + profile_dir)
sys.exit(1)
subprocess.check_call([buildconfig.substs['LLVM_PROFDATA'], 'merge',
'-o', 'merged.profdata'] + profraw_files)

View file

@ -43,17 +43,17 @@ set_config('MOZ_PROFILE_USE',
depends_if('--enable-profile-use')(lambda _: True)) depends_if('--enable-profile-use')(lambda _: True))
@depends('--with-pgo-profile-path', '--enable-profile-use', llvm_profdata) @depends('--with-pgo-profile-path', '--enable-profile-use', llvm_profdata, check_build_environment)
@imports('os') @imports('os')
def pgo_profile_path(path, pgo_use, profdata): def pgo_profile_path(path, pgo_use, profdata, build_env):
if not path: if not path:
return return os.path.join(build_env.topobjdir, 'merged.profdata')
if path and not pgo_use: if path and not pgo_use:
die('Pass --enable-profile-use to use --with-pgo-profile-path.') die('Pass --enable-profile-use to use --with-pgo-profile-path.')
if path and not profdata: if path and not profdata:
die('LLVM_PROFDATA must be set to process the pgo profile.') die('LLVM_PROFDATA must be set to process the pgo profile.')
if not os.path.isdir(path[0]): if not os.path.isfile(path[0]):
die('Argument to --with-pgo-profile-path must be a directory.') die('Argument to --with-pgo-profile-path must be a file.')
if not os.path.isabs(path[0]): if not os.path.isabs(path[0]):
die('Argument to --with-pgo-profile-path must be an absolute path.') die('Argument to --with-pgo-profile-path must be an absolute path.')
return path[0] return path[0]
@ -61,10 +61,10 @@ def pgo_profile_path(path, pgo_use, profdata):
set_config('PGO_PROFILE_PATH', pgo_profile_path) set_config('PGO_PROFILE_PATH', pgo_profile_path)
@depends(c_compiler, check_build_environment, target) @depends(c_compiler, check_build_environment, target, pgo_profile_path)
@imports('multiprocessing') @imports('multiprocessing')
@imports(_from='__builtin__', _import='min') @imports(_from='__builtin__', _import='min')
def pgo_flags(compiler, build_env, target): def pgo_flags(compiler, build_env, target, profdata):
topobjdir = build_env.topobjdir topobjdir = build_env.topobjdir
if topobjdir.endswith('/js/src'): if topobjdir.endswith('/js/src'):
topobjdir = topobjdir[:-7] topobjdir = topobjdir[:-7]
@ -79,7 +79,6 @@ def pgo_flags(compiler, build_env, target):
) )
if compiler.type in ('clang-cl', 'clang'): if compiler.type in ('clang-cl', 'clang'):
profdata = os.path.join(topobjdir, 'merged.profdata')
prefix = '' prefix = ''
if compiler.type == 'clang-cl': if compiler.type == 'clang-cl':
prefix = '/clang:' prefix = '/clang:'

View file

@ -10,6 +10,6 @@ if [ -z "$USE_ARTIFACT" ]; then
export MOZ_LTO=cross export MOZ_LTO=cross
ac_add_options --enable-profile-use ac_add_options --enable-profile-use
ac_add_options --with-pgo-jarlog="${WORKSPACE}/fetches/en-US.log" ac_add_options --with-pgo-jarlog="${WORKSPACE}/fetches/en-US.log"
ac_add_options --with-pgo-profile-path="${WORKSPACE}/fetches" ac_add_options --with-pgo-profile-path="${WORKSPACE}/fetches/merged.profdata"
fi fi
fi fi

View file

@ -7,6 +7,8 @@
import json import json
import os import os
import sys import sys
import glob
import subprocess
from mozbuild.base import MozbuildObject from mozbuild.base import MozbuildObject
from mozfile import TemporaryDirectory from mozfile import TemporaryDirectory
@ -139,3 +141,21 @@ if __name__ == '__main__':
with open(logfile) as f: with open(logfile) as f:
print(f.read()) print(f.read())
sys.exit(ret) sys.exit(ret)
llvm_profdata = env.get('LLVM_PROFDATA')
if llvm_profdata:
profraw_files = glob.glob('*.profraw')
if not profraw_files:
print('Could not find profraw files in the current directory: %s' % os.getcwd())
sys.exit(1)
merge_cmd = [
llvm_profdata,
'merge',
'-o',
'merged.profdata',
] + profraw_files
rc = subprocess.call(merge_cmd)
if rc != 0:
print('INFRA-ERROR: Failed to merge profile data. Corrupt profile?')
# exit with TBPL_RETRY
sys.exit(4)

View file

@ -30,7 +30,7 @@ else
if [ -n "$MOZ_PGO_PROFILE_USE" ]; then if [ -n "$MOZ_PGO_PROFILE_USE" ]; then
ac_add_options --enable-profile-use=cross ac_add_options --enable-profile-use=cross
ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log
ac_add_options --with-pgo-profile-path=/builds/worker/fetches ac_add_options --with-pgo-profile-path=/builds/worker/fetches/merged.profdata
fi fi
fi fi
export LLVM_PROFDATA="$MOZ_FETCHES_DIR/clang/bin/llvm-profdata" export LLVM_PROFDATA="$MOZ_FETCHES_DIR/clang/bin/llvm-profdata"

View file

@ -136,7 +136,7 @@ target_rust_ltoable := force-cargo-library-build
target_rust_nonltoable := force-cargo-test-run force-cargo-library-check $(foreach b,build check,force-cargo-program-$(b)) target_rust_nonltoable := force-cargo-test-run force-cargo-library-check $(foreach b,build check,force-cargo-program-$(b))
ifdef MOZ_PGO_RUST ifdef MOZ_PGO_RUST
rust_pgo_flags := $(if $(MOZ_PROFILE_GENERATE),-C profile-generate=$(topobjdir)) $(if $(MOZ_PROFILE_USE),-C profile-use=$(topobjdir)/merged.profdata) rust_pgo_flags := $(if $(MOZ_PROFILE_GENERATE),-C profile-generate=$(topobjdir)) $(if $(MOZ_PROFILE_USE),-C profile-use=$(PGO_PROFILE_PATH))
endif endif
$(target_rust_ltoable): RUSTFLAGS:=$(rustflags_override) $(RUSTFLAGS) $(if $(MOZ_LTO_RUST),-Clinker-plugin-lto) $(rust_pgo_flags) $(target_rust_ltoable): RUSTFLAGS:=$(rustflags_override) $(RUSTFLAGS) $(if $(MOZ_LTO_RUST),-Clinker-plugin-lto) $(rust_pgo_flags)

View file

@ -100,7 +100,7 @@ if [ -n "$MOZ_PGO_PROFILE_USE" ]; then
# This is disabled because jarlog re-ordering breaks apk publishing tasks, # This is disabled because jarlog re-ordering breaks apk publishing tasks,
# see bug 1539933. # see bug 1539933.
# ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log # ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log
ac_add_options --with-pgo-profile-path=/builds/worker/fetches ac_add_options --with-pgo-profile-path=/builds/worker/fetches/merged.profdata
fi fi
# Package js shell. # Package js shell.

View file

@ -153,16 +153,6 @@ if not CONFIG['JS_STANDALONE'] or not CONFIG['MOZ_BUILD_APP']:
'build', 'build',
] ]
if CONFIG['PGO_PROFILE_PATH']:
profdata_gen = ('merged.profdata.stub', 'merged.profdata')
GENERATED_FILES += [
profdata_gen
]
GENERATED_FILES[profdata_gen].script = 'build/merge_profdata.py'
GENERATED_FILES[profdata_gen].inputs = [
'/' + CONFIG['PGO_PROFILE_PATH'],
]
DIRS += [ DIRS += [
'mfbt', 'mfbt',
] ]

View file

@ -56,6 +56,9 @@ jobs:
cwd: '{checkout}' cwd: '{checkout}'
command: > command: >
./taskcluster/scripts/misc/run-profileserver.sh ./taskcluster/scripts/misc/run-profileserver.sh
fetches:
toolchain:
- linux64-clang
linux64-shippable/opt: linux64-shippable/opt:
description: "Linux64 Profile Generation" description: "Linux64 Profile Generation"
@ -90,6 +93,9 @@ jobs:
cwd: '{checkout}' cwd: '{checkout}'
command: > command: >
./taskcluster/scripts/misc/run-profileserver.sh ./taskcluster/scripts/misc/run-profileserver.sh
fetches:
toolchain:
- linux64-clang
android-api-16/pgo: android-api-16/pgo:
description: "Android 4.0 api-16+ Profile Generation" description: "Android 4.0 api-16+ Profile Generation"
@ -159,6 +165,9 @@ jobs:
sparse-profile: profile-generate sparse-profile: profile-generate
cwd: '{checkout}' cwd: '{checkout}'
command: ./taskcluster/scripts/misc/run-profileserver.sh command: ./taskcluster/scripts/misc/run-profileserver.sh
fetches:
toolchain:
- win64-clang-cl
win64-shippable/opt: win64-shippable/opt:
description: "Win64 Profile Generation" description: "Win64 Profile Generation"
@ -189,3 +198,6 @@ jobs:
sparse-profile: profile-generate sparse-profile: profile-generate
cwd: '{checkout}' cwd: '{checkout}'
command: ./taskcluster/scripts/misc/run-profileserver.sh command: ./taskcluster/scripts/misc/run-profileserver.sh
fetches:
toolchain:
- win64-clang-cl

View file

@ -14,6 +14,7 @@ export UPLOAD_PATH
PGO_RUNDIR=obj-firefox/dist PGO_RUNDIR=obj-firefox/dist
export JARLOG_FILE="en-US.log" export JARLOG_FILE="en-US.log"
export LLVM_PROFDATA=$MOZ_FETCHES_DIR/clang/bin/llvm-profdata
set -v set -v
@ -38,10 +39,4 @@ mkdir -p $UPLOAD_PATH
mv $MOZ_FETCHES_DIR/firefox $PGO_RUNDIR mv $MOZ_FETCHES_DIR/firefox $PGO_RUNDIR
./mach python build/pgo/profileserver.py --binary $PGO_RUNDIR/firefox/firefox ./mach python build/pgo/profileserver.py --binary $PGO_RUNDIR/firefox/firefox
# Fail the build if for some reason we didn't collect any profile data. tar -acvf $UPLOAD_PATH/profdata.tar.xz merged.profdata en-US.log
if test -z "$(find . -maxdepth 1 -name '*.profraw' -print -quit)"; then
echo "ERROR: no profile data produced"
exit 1
fi
tar -acvf $UPLOAD_PATH/profdata.tar.xz *.profraw en-US.log

View file

@ -270,10 +270,6 @@ class AndroidProfileRun(TestingMixin, BaseScript, MozbaseMixin,
self.fatal('INFRA-ERROR: Failed with an ADBTimeoutError', self.fatal('INFRA-ERROR: Failed with an ADBTimeoutError',
EXIT_STATUS_DICT[TBPL_RETRY]) EXIT_STATUS_DICT[TBPL_RETRY])
# We normally merge as part of a GENERATED_FILES step in the profile-use
# build, but Android runs sometimes result in a truncated profile. We do
# a merge here to make sure the data isn't corrupt so we can retry the
# 'run' task if necessary.
profraw_files = glob.glob('/builds/worker/workspace/*.profraw') profraw_files = glob.glob('/builds/worker/workspace/*.profraw')
if not profraw_files: if not profraw_files:
self.fatal('Could not find any profraw files in /builds/worker/workspace') self.fatal('Could not find any profraw files in /builds/worker/workspace')
@ -281,7 +277,7 @@ class AndroidProfileRun(TestingMixin, BaseScript, MozbaseMixin,
os.path.join(os.environ['MOZ_FETCHES_DIR'], 'clang/bin/llvm-profdata'), os.path.join(os.environ['MOZ_FETCHES_DIR'], 'clang/bin/llvm-profdata'),
'merge', 'merge',
'-o', '-o',
'/builds/worker/workspace/merged.profraw', '/builds/worker/workspace/merged.profdata',
] + profraw_files ] + profraw_files
rc = subprocess.call(merge_cmd) rc = subprocess.call(merge_cmd)
if rc != 0: if rc != 0:
@ -294,7 +290,7 @@ class AndroidProfileRun(TestingMixin, BaseScript, MozbaseMixin,
'-acvf', '-acvf',
'/builds/worker/artifacts/profdata.tar.xz', '/builds/worker/artifacts/profdata.tar.xz',
'-C', '/builds/worker/workspace', '-C', '/builds/worker/workspace',
'merged.profraw', 'merged.profdata',
'en-US.log', 'en-US.log',
] ]
subprocess.check_call(tar_cmd) subprocess.check_call(tar_cmd)