aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2021-12-27 16:56:25 +0100
committerGitHub <noreply@github.com>2021-12-27 16:56:25 +0100
commit0e90b13ab1df925e549b5d55853b65911b4b40d3 (patch)
tree5ead59578dee00cde7b503a31d537757546c0511 /src
parentaf553b20902b8b8efbccab5f880879b09e95eb32 (diff)
parenta4ab0a74d97c7c31df69f04870fa56cde89701a3 (diff)
Merge pull request #5835 from yorickvP/fast-repl-load
Fix accidental O(n^2 * log n) performance in NixRepl::addAttrsToScope
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/nixexpr.hh7
-rw-r--r--src/nix/repl.cc12
2 files changed, 17 insertions, 2 deletions
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index c013f5deb..b328b3941 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -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);
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index 63ccbfda3..39a5a31de 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -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());
}