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 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); 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(); }); [&]() { 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)) if (info.ca.has_value() && !info.isContentAddressed(*this))
throw Error( 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 efficiently query whether a path is an output of some
derivation. */ derivation. */
if (info.path.isDerivation()) { if (info.path.isDerivation()) {
auto drv = readInvalidDerivation(info.path); auto parsedDrv = readInvalidDerivation(info.path);
/* Verify that the output paths in the derivation are correct /* Verify that the output paths in the derivation are correct
(i.e., follow the scheme for computing output paths from (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 DB transaction is rolled back, so the path validity
registration above is undone. */ registration above is undone. */
if (checkOutputs) 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 /* Floating CA derivations have indeterminate output paths until
they are built, so don't register anything in that case */ they are built, so don't register anything in that case */
if (i.second.second) if (i.second.second)
cacheDrvOutputMapping(state, id, i.first, *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)}); 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); SQLiteTxn txn(state->db);
StorePathSet paths; StorePathSet paths;
std::map<StorePath, Derivation> derivations;
for (auto & [_, i] : infos) { for (auto & [_, i] : infos) {
assert(i.narHash.algo == HashAlgorithm::SHA256); assert(i.narHash.algo == HashAlgorithm::SHA256);
if (isValidPath_(*state, i.path)) if (isValidPath_(*state, i.path))
updatePathInfo(*state, i); 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); addValidPath(*state, i, false);
}
paths.insert(i.path); paths.insert(i.path);
} }
@ -944,8 +954,11 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
not be valid yet. */ not be valid yet. */
for (auto & [_, i] : infos) for (auto & [_, i] : infos)
if (i.path.isDerivation()) { if (i.path.isDerivation()) {
// FIXME: inefficient; we already loaded the derivation in addValidPath(). if (auto drv = derivations.find(i.path); drv != derivations.end()) {
readInvalidDerivation(i.path).checkInvariants(*this, i.path); 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 /* Do a topological sort of the paths. This will throw an