Skip to content

Commit

Permalink
Fix accidental O(n^2 * log n) performance in NixRepl::addAttrsToScope
Browse files Browse the repository at this point in the history
Only sort once, after adding all of the attrs first. This reduces my
`nix repl '<nixpkgs>'` loading time from 1.07s to 103ms.

Fixes #5823
  • Loading branch information
yorickvP committed Dec 27, 2021
1 parent af553b2 commit a4ab0a7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/libexpr/nixexpr.hh
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ struct StaticEnv
[](const Vars::value_type & a, const Vars::value_type & b) { return a.first < b.first; });
}

void deduplicate()
{
const auto last = std::unique(vars.begin(), vars.end(),
[] (const Vars::value_type & a, const Vars::value_type & b) { return a.first == b.first; });
vars.erase(last, vars.end());
}

Vars::const_iterator find(const Symbol & name) const
{
Vars::value_type key(name, 0);
Expand Down
12 changes: 10 additions & 2 deletions src/nix/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,16 @@ void NixRepl::reloadFiles()
void NixRepl::addAttrsToScope(Value & attrs)
{
state->forceAttrs(attrs);
for (auto & i : *attrs.attrs)
addVarToScope(i.name, *i.value);
if (displ + attrs.attrs->size() >= envSize)
throw Error("environment full; cannot add more variables");

for (auto & i : *attrs.attrs) {
staticEnv.vars.emplace_back(i.name, displ);
env->values[displ++] = i.value;
varNames.insert((string) i.name);
}
staticEnv.sort();
staticEnv.deduplicate();
notice("Added %1% variables.", attrs.attrs->size());
}

Expand Down

0 comments on commit a4ab0a7

Please sign in to comment.