Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libstore: change max-jobs default to auto #9039

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions doc/manual/generate-settings.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
let
inherit (builtins) attrValues concatStringsSep isAttrs isBool mapAttrs;
inherit (builtins) attrValues concatStringsSep isAttrs isBool isString mapAttrs;
inherit (import ./utils.nix) concatStrings indent optionalString squash;
in

Expand All @@ -8,7 +8,7 @@ in

let

showSetting = prefix: setting: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }:
showSetting = prefix: setting: { description, defaultValue, defaultText, aliases, value, experimentalFeature }:
let
result = squash ''
- ${item}
Expand All @@ -24,7 +24,7 @@ let

${experimentalFeatureNote}

**Default:** ${showDefault documentDefault defaultValue}
**Default:** ${if isString defaultText then defaultText else showDefault defaultValue}

${showAliases aliases}
'';
Expand All @@ -45,17 +45,15 @@ let
```
'';

showDefault = documentDefault: defaultValue:
if documentDefault then
# a StringMap value type is specified as a string, but
# this shows the value type. The empty stringmap is `null` in
# JSON, but that converts to `{ }` here.
if defaultValue == "" || defaultValue == [] || isAttrs defaultValue
then "*empty*"
else if isBool defaultValue then
if defaultValue then "`true`" else "`false`"
else "`${toString defaultValue}`"
else "*machine-specific*";
showDefault = defaultValue:
# a StringMap value type is specified as a string, but
# this shows the value type. The empty stringmap is `null` in
# JSON, but that converts to `{ }` here.
if defaultValue == "" || defaultValue == [] || isAttrs defaultValue
then "*empty*"
else if isBool defaultValue then
if defaultValue then "`true`" else "`false`"
else "`${toString defaultValue}`";

showAliases = aliases:
optionalString (aliases != [])
Expand Down
4 changes: 3 additions & 1 deletion doc/manual/src/release-notes/rl-next.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@

- The flake-specific flags `--recreate-lock-file` and `--update-input` have been removed from all commands operating on installables.
They are superceded by `nix flake update`.

- Commit signature verification for the [`builtins.fetchGit`](@docroot@/language/builtins.md#builtins-fetchGit) is added as the new [`verified-fetches` experimental feature](@docroot@/contributing/experimental-features.md#xp-feature-verified-fetches).

- The [`max-jobs` setting](@docroot@/command-ref/conf-file.md#conf-max-jobs) now defaults to `auto`.
8 changes: 4 additions & 4 deletions src/libfetchers/fetch-settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,24 @@ struct FetchSettings : public Config

When empty, disables the global flake registry.
)",
{}, true, Xp::Flakes};
{}, std::nullopt, Xp::Flakes};


Setting<bool> useRegistries{this, true, "use-registries",
"Whether to use flake registries to resolve flake references.",
{}, true, Xp::Flakes};
{}, std::nullopt, Xp::Flakes};

Setting<bool> acceptFlakeConfig{this, false, "accept-flake-config",
"Whether to accept nix configuration from a flake without prompting.",
{}, true, Xp::Flakes};
{}, std::nullopt, Xp::Flakes};

Setting<std::string> commitLockFileSummary{
this, "", "commit-lockfile-summary",
R"(
The commit summary to use when committing changed flake lock files. If
empty, the summary is generated based on the action performed.
)",
{}, true, Xp::Flakes};
{}, std::nullopt, Xp::Flakes};
};

// FIXME: don't use a global variable.
Expand Down
16 changes: 7 additions & 9 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,12 @@ std::vector<Path> getUserConfigFiles()

unsigned int Settings::getDefaultCores()
{
const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
const unsigned int maxCPU = getMaxCPU();

if (maxCPU > 0)
return maxCPU;
else
return concurrency;
return getMaxThreads();
}

#if __APPLE__
Expand Down Expand Up @@ -297,13 +296,12 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s

unsigned int MaxBuildJobsSetting::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 *n;
else
throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
}
if (str == "auto") return getMaxThreads();
Enzime marked this conversation as resolved.
Show resolved Hide resolved

if (auto n = string2Int<decltype(value)>(str))
return *n;
else
throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
}


Expand Down
49 changes: 24 additions & 25 deletions src/libstore/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
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)
const std::set<std::string> & aliases = {},
const std::optional<std::string> defaultText = std::nullopt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these constructor parameters should ideally be by value and then std::moved further. Then the way the caller calls it (with lvalues or rvalues) unnecessary copies can be avoided.

: BaseSetting<unsigned int>(def, name, description, aliases, defaultText)
{
options->addSetting(this);
}
Expand All @@ -38,8 +39,9 @@ struct PluginFilesSetting : public BaseSetting<Paths>
const Paths & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {})
: BaseSetting<Paths>(def, true, name, description, aliases)
const std::set<std::string> & aliases = {},
const std::optional<std::string> defaultText = std::nullopt)
: BaseSetting<Paths>(def, name, description, aliases, defaultText)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

{
options->addSetting(this);
}
Expand Down Expand Up @@ -148,17 +150,17 @@ public:
"the log to show if a build fails."};

MaxBuildJobsSetting maxBuildJobs{
this, 1, "max-jobs",
this, getMaxThreads(), "max-jobs",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A default of getMaxThreads() makes documentation generation non-reproducible. It may be better to represent the "auto" value explicitly, e.g. by changing the type of this option to std::optional<unsigned int>, with "auto" encoded as std::nullopt.

R"(
This option defines the maximum number of jobs that Nix will try to
build in parallel. The default is `1`. The special value `auto`
causes Nix to use the number of CPUs in your system. `0` is useful
when using remote builders to prevent any local builds (except for
`preferLocalBuild` derivation attribute which executes locally
regardless). It can be overridden using the `--max-jobs` (`-j`)
command line switch.
build in parallel. The default is `auto` which causes Nix to use
the number of CPUs in your system.
It can be overridden using the `--max-jobs` / `-j` command line option.

Setting this to `0` when using remote builders will prevent any local builds.
The [`preferLocalBuild`](@docroot@/language/advanced-attributes.md#adv-attr-preferLocalBuild) derivation attribute will make the build always execute locally.
)",
{"build-max-jobs"}};
{"build-max-jobs"}, "`auto`"};

Setting<unsigned int> maxSubstitutionJobs{
this, 16, "max-substitution-jobs",
Expand All @@ -183,7 +185,7 @@ public:
command line switch and defaults to `1`. The value `0` means that
the builder should use all available CPU cores in the system.
)",
{"build-cores"}, false};
{"build-cores"}, "`0`"};

/**
* Read-only mode. Don't copy stuff to the store, don't change
Expand Down Expand Up @@ -260,7 +262,7 @@ public:
R"(
A semicolon-separated list of build machines.
For the exact format and examples, see [the manual chapter on remote builds](../advanced-topics/distributed-builds.md)
)"};
)", {}, "`@$NIX_CONF_DIR/machines`"};

Setting<bool> alwaysAllowSubstitutes{
this, false, "always-allow-substitutes",
Expand Down Expand Up @@ -295,7 +297,7 @@ public:
)"};

Setting<bool> useSQLiteWAL{this, !isWSL1(), "use-sqlite-wal",
"Whether SQLite should use WAL mode."};
"Whether SQLite should use WAL mode.", {}, "`false` if using WSL1, `true` otherwise"};

Setting<bool> syncBeforeRegistering{this, false, "sync-before-registering",
"Whether to call `sync()` before registering a path as valid."};
Expand Down Expand Up @@ -341,18 +343,16 @@ public:
`NIX_REMOTE` is empty, the uid under which the Nix daemon runs if
`NIX_REMOTE` is `daemon`). Obviously, this should not be used
with a nix daemon accessible to untrusted clients.

Defaults to `nixbld` when running as root, *empty* otherwise.
)",
{}, false};
{}, "`nixbld` when running as root, *empty* otherwise"};

Setting<bool> autoAllocateUids{this, false, "auto-allocate-uids",
R"(
Whether to select UIDs for builds automatically, instead of using the
users in `build-users-group`.

UIDs are allocated starting at 872415232 (0x34000000) on Linux and 56930 on macOS.
)", {}, true, Xp::AutoAllocateUids};
)", {}, std::nullopt, Xp::AutoAllocateUids};

Setting<uint32_t> startId{this,
#if __linux__
Expand Down Expand Up @@ -699,7 +699,7 @@ public:

Build systems will usually detect the target platform to be the current physical system and therefore produce machine code incompatible with what may be intended in the derivation.
You should design your derivation's `builder` accordingly and cross-check the results when using this option against natively-built versions of your derivation.
)", {}, false};
)", {}, "*machine-specific*"};

Setting<StringSet> systemFeatures{
this,
Expand Down Expand Up @@ -744,7 +744,7 @@ public:
[nspawn]: https://github.com/NixOS/nix/blob/67bcb99700a0da1395fa063d7c6586740b304598/tests/systemd-nspawn.nix.

Included by default on Linux if the [`auto-allocate-uids`](#conf-auto-allocate-uids) setting is enabled.
)", {}, false};
)", {}, "*machine-specific*"};

Setting<Strings> substituters{
this,
Expand Down Expand Up @@ -878,8 +878,7 @@ public:
R"(
If set to an absolute path to a `netrc` file, Nix will use the HTTP
authentication credentials in this file when trying to download from
a remote host through HTTP or HTTPS. Defaults to
`$NIX_CONF_DIR/netrc`.
a remote host through HTTP or HTTPS.

The `netrc` file consists of a list of accounts in the following
format:
Expand All @@ -896,7 +895,7 @@ public:
> This must be an absolute path, and `~` is not resolved. For
> example, `~/.netrc` won't resolve to your home directory's
> `.netrc`.
)"};
)", {}, "`$NIX_CONF_DIR/netrc`"};

Setting<Path> caFile{
this, getDefaultSSLCertFile(), "ssl-cert-file",
Expand Down Expand Up @@ -1081,7 +1080,7 @@ public:
setting private access tokens when fetching a private repository.
)",
{}, // aliases
true, // document default
std::nullopt, // default text
Xp::ConfigurableImpureEnv
};
};
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/abstract-setting-to-json.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ std::map<std::string, nlohmann::json> BaseSetting<T>::toJSONObject()
auto obj = AbstractSetting::toJSONObject();
obj.emplace("value", value);
obj.emplace("defaultValue", defaultValue);
obj.emplace("documentDefault", documentDefault);
obj.emplace("defaultText", defaultText);
return obj;
}
}
10 changes: 6 additions & 4 deletions src/libutil/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,9 @@ PathSetting::PathSetting(Config * options,
const Path & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases)
: BaseSetting<Path>(def, true, name, description, aliases)
const std::set<std::string> & aliases,
const std::optional<std::string> defaultText)
: BaseSetting<Path>(def, name, description, aliases, defaultText)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok there are many possibilities to do call-by-value optimizations in constructors here. maybe just leave it as is and i open a pr on that on another occasion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, maybe... wait, is this meant to be const references to string literals in the code where all the settings are defined, and none of them are dynamic? @Ericson2314

{
options->addSetting(this);
}
Expand All @@ -423,8 +424,9 @@ OptionalPathSetting::OptionalPathSetting(Config * options,
const std::optional<Path> & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases)
: BaseSetting<std::optional<Path>>(def, true, name, description, aliases)
const std::set<std::string> & aliases,
const std::optional<std::string> defaultText)
: BaseSetting<std::optional<Path>>(def, name, description, aliases, defaultText)
{
options->addSetting(this);
}
Expand Down
16 changes: 9 additions & 7 deletions src/libutil/config.hh
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ protected:

T value;
const T defaultValue;
const bool documentDefault;
const std::optional<std::string> defaultText;

/**
* Parse the string into a `T`.
Expand All @@ -252,15 +252,15 @@ protected:
public:

BaseSetting(const T & def,
const bool documentDefault,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {},
const std::optional<std::string> defaultText = std::nullopt,
std::optional<ExperimentalFeature> experimentalFeature = std::nullopt)
: AbstractSetting(name, description, aliases, experimentalFeature)
, value(def)
, defaultValue(def)
, documentDefault(documentDefault)
, defaultText(defaultText)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plz use std::move here as this is by value

{ }

operator const T &() const { return value; }
Expand Down Expand Up @@ -327,9 +327,9 @@ public:
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {},
const bool documentDefault = true,
const std::optional<std::string> defaultText = std::nullopt,
std::optional<ExperimentalFeature> experimentalFeature = std::nullopt)
: BaseSetting<T>(def, documentDefault, name, description, aliases, experimentalFeature)
: BaseSetting<T>(def, name, description, aliases, defaultText, experimentalFeature)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

{
options->addSetting(this);
}
Expand All @@ -352,7 +352,8 @@ public:
const Path & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {});
const std::set<std::string> & aliases = {},
const std::optional<std::string> defaultText = std::nullopt);

Path parse(const std::string & str) const override;

Expand All @@ -374,7 +375,8 @@ public:
const std::optional<Path> & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {});
const std::set<std::string> & aliases = {},
const std::optional<std::string> defaultText = std::nullopt);

std::optional<Path> parse(const std::string & str) const override;

Expand Down
6 changes: 3 additions & 3 deletions src/libutil/tests/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ namespace nix {
"aliases": [],
"defaultValue": "",
"description": "description\n",
"documentDefault": true,
"defaultText": null,
"value": "value",
"experimentalFeature": null
}
Expand All @@ -190,7 +190,7 @@ namespace nix {
"name-of-the-setting",
"description",
{},
true,
"default-text",
Xp::Flakes,
};
setting.assign("value");
Expand All @@ -201,7 +201,7 @@ namespace nix {
"aliases": [],
"defaultValue": "",
"description": "description\n",
"documentDefault": true,
"defaultText": "default-text",
"value": "value",
"experimentalFeature": "flakes"
}
Expand Down
5 changes: 5 additions & 0 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,11 @@ void drainFD(int fd, Sink & sink, bool block)

//////////////////////////////////////////////////////////////////////

unsigned int getMaxThreads()
{
return std::max(1U, std::thread::hardware_concurrency());
}

unsigned int getMaxCPU()
{
#if __linux__
Expand Down
Loading