1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-22 17:01:08 +01:00

libstore: reuse parsed derivations in registerValidPaths

- LocalStore::registerValidPaths() parsed derivations twice: once in addValidPath() and again when calling checkInvariants(), despite already having loaded the derivation.
- Plumb the parsed Derivation out of addValidPath() and reuse it for the invariant check pass, falling back to re-parsing only when a derivation wasn’t newly registered in this call.
- BM_RegisterValidPathsDerivations/200_mean runs 32% faster
This commit is contained in:
Kamil Monicz 2025-12-18 03:46:44 +00:00
parent 9d2100a165
commit cccfa385e6
No known key found for this signature in database
GPG key ID: F9FB19F1C1DC9C23
2 changed files with 22 additions and 8 deletions

View file

@ -420,7 +420,8 @@ private:
uint64_t queryValidPathId(State & state, const StorePath & path);
uint64_t addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs = true);
uint64_t
addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs = true, Derivation * drv = nullptr);
void invalidatePath(State & state, const StorePath & path);

View file

@ -647,7 +647,7 @@ void LocalStore::cacheDrvOutputMapping(
[&]() { state.stmts->AddDerivationOutput.use()(deriver)(outputName) (printStorePath(output)).exec(); });
}
uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs)
uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs, Derivation * drv)
{
if (info.ca.has_value() && !info.isContentAddressed(*this))
throw Error(
@ -668,7 +668,7 @@ uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, boo
efficiently query whether a path is an output of some
derivation. */
if (info.path.isDerivation()) {
auto drv = readInvalidDerivation(info.path);
auto parsedDrv = readInvalidDerivation(info.path);
/* Verify that the output paths in the derivation are correct
(i.e., follow the scheme for computing output paths from
@ -676,14 +676,17 @@ uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, boo
DB transaction is rolled back, so the path validity
registration above is undone. */
if (checkOutputs)
drv.checkInvariants(*this, info.path);
parsedDrv.checkInvariants(*this, info.path);
for (auto & i : drv.outputsAndOptPaths(*this)) {
for (auto & i : parsedDrv.outputsAndOptPaths(*this)) {
/* Floating CA derivations have indeterminate output paths until
they are built, so don't register anything in that case */
if (i.second.second)
cacheDrvOutputMapping(state, id, i.first, *i.second.second);
}
if (drv)
*drv = std::move(parsedDrv);
}
pathInfoCache->lock()->upsert(info.path, PathInfoCacheValue{.value = std::make_shared<const ValidPathInfo>(info)});
@ -924,12 +927,19 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
SQLiteTxn txn(state->db);
StorePathSet paths;
std::map<StorePath, Derivation> derivations;
for (auto & [_, i] : infos) {
assert(i.narHash.algo == HashAlgorithm::SHA256);
if (isValidPath_(*state, i.path))
updatePathInfo(*state, i);
else
else if (i.path.isDerivation()) {
Derivation drv;
addValidPath(*state, i, false, &drv);
derivations.emplace(i.path, std::move(drv));
} else {
addValidPath(*state, i, false);
}
paths.insert(i.path);
}
@ -944,9 +954,12 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
not be valid yet. */
for (auto & [_, i] : infos)
if (i.path.isDerivation()) {
// FIXME: inefficient; we already loaded the derivation in addValidPath().
if (auto drv = derivations.find(i.path); drv != derivations.end()) {
drv->second.checkInvariants(*this, i.path);
} else {
readInvalidDerivation(i.path).checkInvariants(*this, i.path);
}
}
/* Do a topological sort of the paths. This will throw an
error if a cycle is detected and roll back the