From 686ad9b05229b724bc785e60ef1d6169f896ef68 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 25 Nov 2025 16:52:43 -0500 Subject: [PATCH] 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 Co-Authored-By: Bernardo Meurer Costa --- src/libstore/unix/build/derivation-builder.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libstore/unix/build/derivation-builder.cc b/src/libstore/unix/build/derivation-builder.cc index 428430086..ebd53472b 100644 --- a/src/libstore/unix/build/derivation-builder.cc +++ b/src/libstore/unix/build/derivation-builder.cc @@ -1398,6 +1398,11 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() StorePathSet refs; }; + /* inverse map of scratchOutputs for efficient lookup */ + std::map scratchOutputsInverse; + for (auto & [outputName, path] : scratchOutputs) + scratchOutputsInverse.insert_or_assign(path, outputName); + std::map> outputReferencesIfUnregistered; std::map outputStats; for (auto & [outputName, _] : drv.outputs) { @@ -1486,11 +1491,9 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs() [&](const AlreadyRegistered &) { return StringSet{}; }, [&](const PerhapsNeedToRegister & refs) { StringSet referencedOutputs; - /* FIXME build inverted map up front so no quadratic waste here */ for (auto & r : refs.refs) - for (auto & [o, p] : scratchOutputs) - if (r == p) - referencedOutputs.insert(o); + if (auto * o = get(scratchOutputsInverse, r)) + referencedOutputs.insert(*o); return referencedOutputs; }, },