1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-04 16:10:59 +01:00

perf(libstore/derivation-builder): pre-compute outputGraph for linear complexity

Build the inverse of `scratchOuputs` before running topoSort, avoiding
quadratic complexity when determining which outputs reference each
other. This fixes the FIXME comment about building the inverted map up
front.

Inspired by Lix commit 10c04ce84 / Change Id
Ibdd46e7b2e895bfeeebc173046d1297b41998181, but ended up being completely
different code.

Co-Authored-By: Maximilian Bosch <maximilian@mbosch.me>
Co-Authored-By: Bernardo Meurer Costa <beme@anthropic.com>
This commit is contained in:
John Ericson 2025-11-25 16:52:43 -05:00
parent 13b4512cbe
commit 686ad9b052

View file

@ -1398,6 +1398,11 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
StorePathSet refs; StorePathSet refs;
}; };
/* inverse map of scratchOutputs for efficient lookup */
std::map<StorePath, std::string> scratchOutputsInverse;
for (auto & [outputName, path] : scratchOutputs)
scratchOutputsInverse.insert_or_assign(path, outputName);
std::map<std::string, std::variant<AlreadyRegistered, PerhapsNeedToRegister>> outputReferencesIfUnregistered; std::map<std::string, std::variant<AlreadyRegistered, PerhapsNeedToRegister>> outputReferencesIfUnregistered;
std::map<std::string, struct stat> outputStats; std::map<std::string, struct stat> outputStats;
for (auto & [outputName, _] : drv.outputs) { for (auto & [outputName, _] : drv.outputs) {
@ -1486,11 +1491,9 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
[&](const AlreadyRegistered &) { return StringSet{}; }, [&](const AlreadyRegistered &) { return StringSet{}; },
[&](const PerhapsNeedToRegister & refs) { [&](const PerhapsNeedToRegister & refs) {
StringSet referencedOutputs; StringSet referencedOutputs;
/* FIXME build inverted map up front so no quadratic waste here */
for (auto & r : refs.refs) for (auto & r : refs.refs)
for (auto & [o, p] : scratchOutputs) if (auto * o = get(scratchOutputsInverse, r))
if (r == p) referencedOutputs.insert(*o);
referencedOutputs.insert(o);
return referencedOutputs; return referencedOutputs;
}, },
}, },