mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Add lazy evaluation for experimental feature reasons
Wrap fmt() calls in lambdas to defer string formatting until the feature check fails. This avoids unnecessary string formatting in the common case where the feature is enabled. Addresses performance concern raised by xokdvium in PR review.
This commit is contained in:
parent
39c4665488
commit
1b96a704d3
4 changed files with 23 additions and 6 deletions
|
|
@ -426,7 +426,9 @@ Derivation parseDerivation(
|
||||||
if (*versionS == "xp-dyn-drv"sv) {
|
if (*versionS == "xp-dyn-drv"sv) {
|
||||||
// Only version we have so far
|
// Only version we have so far
|
||||||
version = DerivationATermVersion::DynamicDerivations;
|
version = DerivationATermVersion::DynamicDerivations;
|
||||||
xpSettings.require(Xp::DynamicDerivations, fmt("derivation '%s', ATerm format version 'xp-dyn-drv'", name));
|
xpSettings.require(Xp::DynamicDerivations, [&] {
|
||||||
|
return fmt("derivation '%s', ATerm format version 'xp-dyn-drv'", name);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
throw FormatError("Unknown derivation ATerm format version '%s'", *versionS);
|
throw FormatError("Unknown derivation ATerm format version '%s'", *versionS);
|
||||||
}
|
}
|
||||||
|
|
@ -1454,7 +1456,8 @@ Derivation Derivation::fromJSON(const nlohmann::json & _json, const Experimental
|
||||||
node.value = getStringSet(valueAt(json, "outputs"));
|
node.value = getStringSet(valueAt(json, "outputs"));
|
||||||
auto drvs = getObject(valueAt(json, "dynamicOutputs"));
|
auto drvs = getObject(valueAt(json, "dynamicOutputs"));
|
||||||
for (auto & [outputId, childNode] : drvs) {
|
for (auto & [outputId, childNode] : drvs) {
|
||||||
xpSettings.require(Xp::DynamicDerivations, fmt("dynamic output '%s' in JSON", outputId));
|
xpSettings.require(
|
||||||
|
Xp::DynamicDerivations, [&] { return fmt("dynamic output '%s' in JSON", outputId); });
|
||||||
node.childMap[outputId] = doInput(childNode);
|
node.childMap[outputId] = doInput(childNode);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,9 @@ void drvRequireExperiment(const SingleDerivedPath & drv, const ExperimentalFeatu
|
||||||
// plain drv path; no experimental features required.
|
// plain drv path; no experimental features required.
|
||||||
},
|
},
|
||||||
[&](const SingleDerivedPath::Built & b) {
|
[&](const SingleDerivedPath::Built & b) {
|
||||||
xpSettings.require(
|
xpSettings.require(Xp::DynamicDerivations, [&] {
|
||||||
Xp::DynamicDerivations,
|
return fmt("building output '%s' of '%s'", b.output, b.drvPath->getBaseStorePath().to_string());
|
||||||
fmt("building output '%s' of '%s'", b.output, b.drvPath->getBaseStorePath().to_string()));
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
drv.raw());
|
drv.raw());
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ DownstreamPlaceholder DownstreamPlaceholder::unknownDerivation(
|
||||||
OutputNameView outputName,
|
OutputNameView outputName,
|
||||||
const ExperimentalFeatureSettings & xpSettings)
|
const ExperimentalFeatureSettings & xpSettings)
|
||||||
{
|
{
|
||||||
xpSettings.require(Xp::DynamicDerivations, fmt("placeholder for unknown derivation output '%s'", outputName));
|
xpSettings.require(
|
||||||
|
Xp::DynamicDerivations, [&] { return fmt("placeholder for unknown derivation output '%s'", outputName); });
|
||||||
auto compressed = compressHash(placeholder.hash, 20);
|
auto compressed = compressHash(placeholder.hash, 20);
|
||||||
auto clearText =
|
auto clearText =
|
||||||
"nix-computed-output:" + compressed.to_string(HashFormat::Nix32, false) + ":" + std::string{outputName};
|
"nix-computed-output:" + compressed.to_string(HashFormat::Nix32, false) + ":" + std::string{outputName};
|
||||||
|
|
|
||||||
|
|
@ -465,6 +465,19 @@ struct ExperimentalFeatureSettings : Config
|
||||||
*/
|
*/
|
||||||
void require(const ExperimentalFeature &, std::string reason = "") const;
|
void require(const ExperimentalFeature &, std::string reason = "") const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require an experimental feature be enabled, throwing an error if it is
|
||||||
|
* not. The reason is lazily evaluated only if the feature is disabled.
|
||||||
|
*/
|
||||||
|
template<typename GetReason>
|
||||||
|
requires std::invocable<GetReason> && std::convertible_to<std::invoke_result_t<GetReason>, std::string>
|
||||||
|
void require(const ExperimentalFeature & feature, GetReason && getReason) const
|
||||||
|
{
|
||||||
|
if (isEnabled(feature))
|
||||||
|
return;
|
||||||
|
require(feature, getReason());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `std::nullopt` pointer means no feature, which means there is nothing that could be
|
* `std::nullopt` pointer means no feature, which means there is nothing that could be
|
||||||
* disabled, and so the function returns true in that case.
|
* disabled, and so the function returns true in that case.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue