firefox: add profile-guided optimization

Lo and behold, we're finally catching up with Mozillas very own firefox
build in terms of speed.

PGO is an optimization technique in which in a first step we create a
build that supports instrumentation, meaning we can use it to create a
profile of how the browser behaved during usage. Then in a second pass
we create the final build that uses the acquired profiling data to
optimize the browser for the workload it actually received during
profiling.

The downside is that with PGO we now need to build Firefox twice, which
increases the build time from around 20 minutes to roughly 50 minutes.

In the Speedometer 2.0 benchmark multiple tests could see a
responsiveness improvemeant around 20-25%, which makes the increased
build time well worth it.

Sadly this benefit seems limited to x86_64-linux, builds on
aarch64-linux get stuck during profiling and I haven't found out why.

Finally, after a long time, we can say:

Closes: #76484
Supersedes: #129503
This commit is contained in:
Martin Weinelt 2022-03-22 03:35:51 +01:00 committed by Yuka
parent f37810ba4d
commit 0d3772f645
3 changed files with 72 additions and 0 deletions

View file

@ -15,6 +15,14 @@
<section xml:id="sec-release-22.05-highlights">
<title>Highlights</title>
<itemizedlist>
<listitem>
<para>
The <literal>firefox</literal> browser on
<literal>x86_64-linux</literal> is now making use of
profile-guided optimization resulting in a much more
responsive browsing experience.
</para>
</listitem>
<listitem>
<para>
<literal>security.acme.defaults</literal> has been added to

View file

@ -6,6 +6,10 @@ In addition to numerous new and upgraded packages, this release has the followin
## Highlights {#sec-release-22.05-highlights}
- The `firefox` browser on `x86_64-linux` is now making use of
profile-guided optimization resulting in a much more responsive
browsing experience.
- `security.acme.defaults` has been added to simplify configuring
settings for many certificates at once. This also opens up the
the option to use DNS-01 validation when using `enableACME` on

View file

@ -83,6 +83,7 @@
, gssSupport ? true, libkrb5
, jemallocSupport ? true, jemalloc
, ltoSupport ? (stdenv.isLinux && stdenv.is64bit), overrideCC, buildPackages
, pgoSupport ? (stdenv.isLinux && stdenv.isx86_64 && stdenv.hostPlatform == stdenv.buildPlatform), xvfb-run
, pipewireSupport ? waylandSupport && webrtcSupport
, pulseaudioSupport ? stdenv.isLinux, libpulseaudio
, waylandSupport ? true, libxkbcommon, libdrm
@ -164,6 +165,13 @@ buildStdenv.mkDerivation ({
inherit src unpackPhase meta;
# Add another configure-build-profiling run before the final configure phase if we build with pgo
preConfigurePhases = lib.optionals pgoSupport [
"configurePhase"
"buildPhase"
"profilingPhase"
];
patches = [
]
++ lib.optional (lib.versionAtLeast version "86") ./env_var_for_system_dir-ff86.patch
@ -199,6 +207,7 @@ buildStdenv.mkDerivation ({
which
wrapGAppsHook
]
++ lib.optionals pgoSupport [ xvfb-run ]
++ extraNativeBuildInputs;
setOutputFlags = false; # `./mach configure` doesn't understand `--*dir=` flags.
@ -214,6 +223,9 @@ buildStdenv.mkDerivation ({
export MOZ_OBJDIR=$(pwd)/mozobj
export MOZBUILD_STATE_PATH=$(pwd)/mozbuild
# Don't try to send libnotify notifications during build
export MOZ_NOSPAM=1
# Set consistent remoting name to ensure wmclass matches with desktop file
export MOZ_APP_REMOTINGNAME="${binaryName}"
@ -228,6 +240,25 @@ buildStdenv.mkDerivation ({
# RBox WASM Sandboxing
export WASM_CC=${pkgsCross.wasi32.stdenv.cc}/bin/${pkgsCross.wasi32.stdenv.cc.targetPrefix}cc
export WASM_CXX=${pkgsCross.wasi32.stdenv.cc}/bin/${pkgsCross.wasi32.stdenv.cc.targetPrefix}c++
'' + lib.optionalString pgoSupport ''
if [ -e "$TMPDIR/merged.profdata" ]; then
echo "Configuring with profiling data"
for i in "''${!configureFlagsArray[@]}"; do
if [[ ''${configureFlagsArray[i]} = "--enable-profile-generate=cross" ]]; then
unset 'configureFlagsArray[i]'
fi
done
configureFlagsArray+=(
"--enable-profile-use=cross"
"--with-pgo-profile-path="$TMPDIR/merged.profdata""
"--with-pgo-jarlog="$TMPDIR/jarlog""
)
else
echo "Configuring to generate profiling data"
configureFlagsArray+=(
"--enable-profile-generate=cross"
)
fi
'' + lib.optionalString googleAPISupport ''
# Google API key used by Chromium and Firefox.
# Note: These are for NixOS/nixpkgs use ONLY. For your own distribution,
@ -336,10 +367,35 @@ buildStdenv.mkDerivation ({
++ lib.optional jemallocSupport jemalloc
++ extraBuildInputs;
profilingPhase = lib.optionalString pgoSupport ''
# Package up Firefox for profiling
./mach package
# Run profiling
(
export HOME=$TMPDIR
export LLVM_PROFDATA=llvm-profdata
export JARLOG_FILE="$TMPDIR/jarlog"
xvfb-run -w 10 -s "-screen 0 1920x1080x24" \
./mach python ./build/pgo/profileserver.py
)
# Copy profiling data to a place we can easily reference
cp ./merged.profdata $TMPDIR/merged.profdata
# Clean build dir
./mach clobber
'';
preBuild = ''
cd mozobj
'';
postBuild = ''
cd ..
'';
makeFlags = extraMakeFlags;
separateDebugInfo = enableDebugSymbols;
enableParallelBuilding = true;
@ -347,6 +403,10 @@ buildStdenv.mkDerivation ({
# tests were disabled in configureFlags
doCheck = false;
preInstall = ''
cd mozobj
'';
postInstall = lib.optionalString buildStdenv.isLinux ''
# Remove SDK cruft. FIXME: move to a separate output?
rm -rf $out/share/idl $out/include $out/lib/${binaryName}-devel-*