From cc0beaee982830788f3ba63afaf9dc2c72bcc086 Mon Sep 17 00:00:00 2001 From: Alex Wied Date: Tue, 2 Aug 2022 15:42:04 -0400 Subject: [PATCH] libstore: Add load-limit setting to dynamically control parallelism --- doc/manual/src/release-notes/rl-next.md | 1 + src/libstore/build/local-derivation-goal.cc | 3 +++ src/libstore/globals.hh | 24 +++++++++++++++++++++ src/nix-build/nix-build.cc | 1 + 4 files changed, 29 insertions(+) diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md index 78ae99f4bb7..fec0155b8f2 100644 --- a/doc/manual/src/release-notes/rl-next.md +++ b/doc/manual/src/release-notes/rl-next.md @@ -1,2 +1,3 @@ # Release X.Y (202?-??-??) +* Add new `load-limit` setting to control the `-lN` flag of GNU Make. diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 6843173a70d..819f3016a5e 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -1069,6 +1069,9 @@ void LocalDerivationGoal::initEnv() /* The maximum number of cores to utilize for parallel building. */ env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str(); + /* If the load average is greater than N, disable parallel building. */ + env["NIX_LOAD_LIMIT"] = (format("%d") % settings.loadLimit).str(); + initTmpDir(); /* Compatibility hack with Nix <= 0.7: if this is a fixed-output diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index d7f351166ad..4f944e4a032 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -142,6 +142,30 @@ public: )", {"build-cores"}, false}; + Setting loadLimit{ + this, + getDefaultCores(), + "load-limit", + R"( + Sets the value of the `NIX_LOAD_LIMIT` environment variable in the + invocation of builders. Builders can use this value at their discretion + to dynamically control the amount of parallelism with respect to the + machine's load average. For instance, in Nixpkgs, if this value is >0, + the builder passes the `-lN` flag to GNU Make. In this case, if the + load average of the machine exceeds `N`, the amount of parallelism will + be dynamically reduced to 1. + + By default, it is set to the number of cores available to Nix. + + On busy machines where Nix co-exists with other workloads, parallelism + may not work as intended. For example, consider a 64 core machine whose + load average is 24 and where Nix is limited to 8 cores. By default, + `-j8 -l8` will be passed to GNU Make. Since the load average exceeds 8, + no parallelism will take place despite the fact that 8 cores are + available. In this case, `load-limit` should be set to `0` to prevent + the `-lN` flag from being passed to GNU Make. + )"}; + /* Read-only mode. Don't copy stuff to the store, don't change the database. */ bool readOnlyMode = false; diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 7eb8c8f6acc..fedf33a81cd 100644 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -469,6 +469,7 @@ static void main_nix_build(int argc, char * * argv) env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = *tmp; env["NIX_STORE"] = store->storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores); + env["NIX_LOAD_LIMIT"] = std::to_string(settings.loadLimit); auto passAsFile = tokenizeString(getOr(drv.env, "passAsFile", ""));