From 0d3772f6455c0185c9dee3f8c31130e7ad6edff9 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 22 Mar 2022 03:35:51 +0100 Subject: [PATCH] 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 --- .../from_md/release-notes/rl-2205.section.xml | 8 +++ .../manual/release-notes/rl-2205.section.md | 4 ++ .../networking/browsers/firefox/common.nix | 60 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 579ef65680d..86c68fcd0ca 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -15,6 +15,14 @@
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 diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index ba4d4c78049..f1bb091b892 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -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 diff --git a/pkgs/applications/networking/browsers/firefox/common.nix b/pkgs/applications/networking/browsers/firefox/common.nix index 64cba1b52a6..8d445ac44eb 100644 --- a/pkgs/applications/networking/browsers/firefox/common.nix +++ b/pkgs/applications/networking/browsers/firefox/common.nix @@ -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-*