aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build/substitution-goal.cc2
-rw-r--r--src/libstore/build/worker.cc25
-rw-r--r--src/libstore/build/worker.hh19
-rw-r--r--src/libstore/globals.cc11
-rw-r--r--src/libstore/globals.hh27
5 files changed, 74 insertions, 10 deletions
diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc
index 190fb455a..30c196894 100644
--- a/src/libstore/build/substitution-goal.cc
+++ b/src/libstore/build/substitution-goal.cc
@@ -204,7 +204,7 @@ void PathSubstitutionGoal::tryToRun()
if maxBuildJobs == 0 (no local builds allowed), we still allow
a substituter to run. This is because substitutions cannot be
distributed to another machine via the build hook. */
- if (worker.getNrLocalBuilds() >= std::max(1U, (unsigned int) settings.maxBuildJobs)) {
+ if (worker.getNrSubstitutions() >= std::max(1U, (unsigned int) settings.maxSubstitutionJobs)) {
worker.waitForBuildSlot(shared_from_this());
return;
}
diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc
index 6ad4a0e2b..85024e4c4 100644
--- a/src/libstore/build/worker.cc
+++ b/src/libstore/build/worker.cc
@@ -18,6 +18,7 @@ Worker::Worker(Store & store, Store & evalStore)
{
/* Debugging: prevent recursive workers. */
nrLocalBuilds = 0;
+ nrSubstitutions = 0;
lastWokenUp = steady_time_point::min();
permanentFailure = false;
timedOut = false;
@@ -176,6 +177,12 @@ unsigned Worker::getNrLocalBuilds()
}
+unsigned Worker::getNrSubstitutions()
+{
+ return nrSubstitutions;
+}
+
+
void Worker::childStarted(GoalPtr goal, const std::set<int> & fds,
bool inBuildSlot, bool respectTimeouts)
{
@@ -187,7 +194,10 @@ void Worker::childStarted(GoalPtr goal, const std::set<int> & fds,
child.inBuildSlot = inBuildSlot;
child.respectTimeouts = respectTimeouts;
children.emplace_back(child);
- if (inBuildSlot) nrLocalBuilds++;
+ if (inBuildSlot) {
+ if (dynamic_cast<PathSubstitutionGoal *>(child.goal2)) nrSubstitutions++;
+ else nrLocalBuilds++;
+ }
}
@@ -198,8 +208,13 @@ void Worker::childTerminated(Goal * goal, bool wakeSleepers)
if (i == children.end()) return;
if (i->inBuildSlot) {
- assert(nrLocalBuilds > 0);
- nrLocalBuilds--;
+ if (dynamic_cast<PathSubstitutionGoal *>(goal)) {
+ assert(nrSubstitutions > 0);
+ nrSubstitutions--;
+ } else {
+ assert(nrLocalBuilds > 0);
+ nrLocalBuilds--;
+ }
}
children.erase(i);
@@ -220,7 +235,9 @@ void Worker::childTerminated(Goal * goal, bool wakeSleepers)
void Worker::waitForBuildSlot(GoalPtr goal)
{
debug("wait for build slot");
- if (getNrLocalBuilds() < settings.maxBuildJobs)
+ bool isSubstitutionGoal = dynamic_cast<PathSubstitutionGoal *>(goal.get());
+ if ((!isSubstitutionGoal && getNrLocalBuilds() < settings.maxBuildJobs) ||
+ (isSubstitutionGoal && getNrSubstitutions() < settings.maxSubstitutionJobs))
wakeUp(goal); /* we can do it right away */
else
addToWeakGoals(wantingToBuild, goal);
diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh
index bb51d641d..63624d910 100644
--- a/src/libstore/build/worker.hh
+++ b/src/libstore/build/worker.hh
@@ -88,12 +88,17 @@ private:
std::list<Child> children;
/**
- * Number of build slots occupied. This includes local builds and
- * substitutions but not remote builds via the build hook.
+ * Number of build slots occupied. This includes local builds but does not
+ * include substitutions or remote builds via the build hook.
*/
unsigned int nrLocalBuilds;
/**
+ * Number of substitution slots occupied.
+ */
+ unsigned int nrSubstitutions;
+
+ /**
* Maps used to prevent multiple instantiations of a goal for the
* same derivation / path.
*/
@@ -220,13 +225,17 @@ public:
void wakeUp(GoalPtr goal);
/**
- * Return the number of local build and substitution processes
- * currently running (but not remote builds via the build
- * hook).
+ * Return the number of local build processes currently running (but not
+ * remote builds via the build hook).
*/
unsigned int getNrLocalBuilds();
/**
+ * Return the number of substitution processes currently running.
+ */
+ unsigned int getNrSubstitutions();
+
+ /**
* Registers a running child process. `inBuildSlot` means that
* the process counts towards the jobs limit.
*/
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 4c66d08ee..46b14cc98 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -249,6 +249,17 @@ unsigned int MaxBuildJobsSetting::parse(const std::string & str) const
}
}
+unsigned int MaxSubstitutionJobsSetting::parse(const std::string & str) const
+{
+ if (str == "auto") return std::max(1U, std::thread::hardware_concurrency());
+ else {
+ if (auto n = string2Int<decltype(value)>(str))
+ return std::max(1U, *n);
+ else
+ throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
+ }
+}
+
Paths PluginFilesSetting::parse(const std::string & str) const
{
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 609cf53b8..f1e1e4b22 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -29,6 +29,21 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
unsigned int parse(const std::string & str) const override;
};
+struct MaxSubstitutionJobsSetting : public BaseSetting<unsigned int>
+{
+ MaxSubstitutionJobsSetting(Config * options,
+ unsigned int def,
+ const std::string & name,
+ const std::string & description,
+ const std::set<std::string> & aliases = {})
+ : BaseSetting<unsigned int>(def, true, name, description, aliases)
+ {
+ options->addSetting(this);
+ }
+
+ unsigned int parse(const std::string & str) const override;
+};
+
struct PluginFilesSetting : public BaseSetting<Paths>
{
bool pluginsLoaded = false;
@@ -159,6 +174,18 @@ public:
)",
{"build-max-jobs"}};
+ MaxSubstitutionJobsSetting maxSubstitutionJobs{
+ this, 16, "max-substitution-jobs",
+ R"(
+ This option defines the maximum number of substitution jobs that Nix
+ will try to run in parallel. The default is `16`. The minimum value
+ one can choose is `1` and lower values will be interpreted as `1`. The
+ special value `auto` causes Nix to use the number of CPUs in your
+ system. It can be overridden using the `--max-substitution-jobs`
+ command line switch.
+ )",
+ {"substitution-max-jobs"}};
+
Setting<unsigned int> buildCores{
this,
getDefaultCores(),