Skip to content

Commit

Permalink
Move EvalState from the stack to the heap
Browse files Browse the repository at this point in the history
EvalState contains a few counters (e.g. nrValues) that increase
quickly enough that they end up being interpreted as pointers by the
garbage collector. Moving it to the heap makes them invisible to the
garbage collector.

This reduces the max RSS doing 100 evaluations of
nixos.tests.firefox.x86_64-linux.drvPath from 455 MiB to 292 MiB.

Note: ideally, allocations would be much further up in the 64-bit
address space to reduce the odds of an integer being misinterpreted as
a pointer. Maybe we can use some linker magic to move the .bss segment
to a higher address.
  • Loading branch information
edolstra committed Jun 12, 2018
1 parent c905d8b commit 0629601
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 46 deletions.
28 changes: 14 additions & 14 deletions src/nix-build/nix-build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,10 @@ void mainWrapped(int argc, char * * argv)

auto store = openStore();

EvalState state(myArgs.searchPath, store);
state.repair = repair;
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
state->repair = repair;

Bindings & autoArgs = *myArgs.getAutoArgs(state);
Bindings & autoArgs = *myArgs.getAutoArgs(*state);

if (packages) {
std::ostringstream joined;
Expand All @@ -268,21 +268,21 @@ void mainWrapped(int argc, char * * argv)
std::vector<Expr *> exprs;

if (readStdin)
exprs = {state.parseStdin()};
exprs = {state->parseStdin()};
else
for (auto i : left) {
auto absolute = i;
try {
absolute = canonPath(absPath(i), true);
} catch (Error e) {};
if (fromArgs)
exprs.push_back(state.parseExprFromString(i, absPath(".")));
exprs.push_back(state->parseExprFromString(i, absPath(".")));
else if (store->isStorePath(absolute) && std::regex_match(absolute, std::regex(".*\\.drv(!.*)?")))
drvs.push_back(DrvInfo(state, store, absolute));
drvs.push_back(DrvInfo(*state, store, absolute));
else
/* If we're in a #! script, interpret filenames
relative to the script. */
exprs.push_back(state.parseExprFromFile(resolveExprPath(state.checkSourcePath(lookupFileArg(state,
exprs.push_back(state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state,
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
}

Expand All @@ -291,12 +291,12 @@ void mainWrapped(int argc, char * * argv)

for (auto e : exprs) {
Value vRoot;
state.eval(e, vRoot);
state->eval(e, vRoot);

for (auto & i : attrPaths) {
Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot));
state.forceValue(v);
getDerivations(state, v, "", autoArgs, drvs, false);
Value & v(*findAlongAttrPath(*state, i, autoArgs, vRoot));
state->forceValue(v);
getDerivations(*state, v, "", autoArgs, drvs, false);
}
}

Expand Down Expand Up @@ -332,12 +332,12 @@ void mainWrapped(int argc, char * * argv)
if (shell == "") {

try {
auto expr = state.parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath("."));
auto expr = state->parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath("."));

Value v;
state.eval(expr, v);
state->eval(expr, v);

auto drv = getDerivation(state, v, false);
auto drv = getDerivation(*state, v, false);
if (!drv)
throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation");

Expand Down
20 changes: 10 additions & 10 deletions src/nix-instantiate/nix-instantiate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,37 +158,37 @@ int main(int argc, char * * argv)

auto store = openStore();

EvalState state(myArgs.searchPath, store);
state.repair = repair;
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
state->repair = repair;

Bindings & autoArgs = *myArgs.getAutoArgs(state);
Bindings & autoArgs = *myArgs.getAutoArgs(*state);

if (attrPaths.empty()) attrPaths = {""};

if (findFile) {
for (auto & i : files) {
Path p = state.findFile(i);
Path p = state->findFile(i);
if (p == "") throw Error(format("unable to find '%1%'") % i);
std::cout << p << std::endl;
}
return;
}

if (readStdin) {
Expr * e = state.parseStdin();
processExpr(state, attrPaths, parseOnly, strict, autoArgs,
Expr * e = state->parseStdin();
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, outputKind, xmlOutputSourceLocation, e);
} else if (files.empty() && !fromArgs)
files.push_back("./default.nix");

for (auto & i : files) {
Expr * e = fromArgs
? state.parseExprFromString(i, absPath("."))
: state.parseExprFromFile(resolveExprPath(state.checkSourcePath(lookupFileArg(state, i))));
processExpr(state, attrPaths, parseOnly, strict, autoArgs,
? state->parseExprFromString(i, absPath("."))
: state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i))));
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, outputKind, xmlOutputSourceLocation, e);
}

state.printStats();
state->printStats();
});
}
28 changes: 14 additions & 14 deletions src/nix-prefetch-url/nix-prefetch-url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ int main(int argc, char * * argv)
throw UsageError("too many arguments");

auto store = openStore();
EvalState state(myArgs.searchPath, store);
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);

Bindings & autoArgs = *myArgs.getAutoArgs(state);
Bindings & autoArgs = *myArgs.getAutoArgs(*state);

/* If -A is given, get the URI from the specified Nix
expression. */
Expand All @@ -107,33 +107,33 @@ int main(int argc, char * * argv)
throw UsageError("you must specify a URI");
uri = args[0];
} else {
Path path = resolveExprPath(lookupFileArg(state, args.empty() ? "." : args[0]));
Path path = resolveExprPath(lookupFileArg(*state, args.empty() ? "." : args[0]));
Value vRoot;
state.evalFile(path, vRoot);
Value & v(*findAlongAttrPath(state, attrPath, autoArgs, vRoot));
state.forceAttrs(v);
state->evalFile(path, vRoot);
Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot));
state->forceAttrs(v);

/* Extract the URI. */
auto attr = v.attrs->find(state.symbols.create("urls"));
auto attr = v.attrs->find(state->symbols.create("urls"));
if (attr == v.attrs->end())
throw Error("attribute set does not contain a 'urls' attribute");
state.forceList(*attr->value);
state->forceList(*attr->value);
if (attr->value->listSize() < 1)
throw Error("'urls' list is empty");
uri = state.forceString(*attr->value->listElems()[0]);
uri = state->forceString(*attr->value->listElems()[0]);

/* Extract the hash mode. */
attr = v.attrs->find(state.symbols.create("outputHashMode"));
attr = v.attrs->find(state->symbols.create("outputHashMode"));
if (attr == v.attrs->end())
printInfo("warning: this does not look like a fetchurl call");
else
unpack = state.forceString(*attr->value) == "recursive";
unpack = state->forceString(*attr->value) == "recursive";

/* Extract the name. */
if (name.empty()) {
attr = v.attrs->find(state.symbols.create("name"));
attr = v.attrs->find(state->symbols.create("name"));
if (attr != v.attrs->end())
name = state.forceString(*attr->value);
name = state->forceString(*attr->value);
}
}

Expand All @@ -158,7 +158,7 @@ int main(int argc, char * * argv)

if (storePath.empty()) {

auto actualUri = resolveMirrorUri(state, uri);
auto actualUri = resolveMirrorUri(*state, uri);

/* Download the file. */
DownloadRequest req(actualUri);
Expand Down
4 changes: 2 additions & 2 deletions src/nix/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,8 @@ struct CmdRepl : StoreCommand, MixEvalArgs

void run(ref<Store> store) override
{
NixRepl repl(searchPath, openStore());
repl.mainLoop(files);
auto repl = std::make_unique<NixRepl>(searchPath, openStore());
repl->mainLoop(files);
}
};

Expand Down
12 changes: 6 additions & 6 deletions src/nix/upgrade-nix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ struct CmdUpgradeNix : StoreCommand
auto req = DownloadRequest("https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/tools/nix-fallback-paths.nix");
auto res = getDownloader()->download(req);

EvalState state(Strings(), store);
auto v = state.allocValue();
state.eval(state.parseExprFromString(*res.data, "/no-such-path"), *v);
Bindings & bindings(*state.allocBindings(0));
auto v2 = findAlongAttrPath(state, settings.thisSystem, bindings, *v);
auto state = std::make_unique<EvalState>(Strings(), store);
auto v = state->allocValue();
state->eval(state->parseExprFromString(*res.data, "/no-such-path"), *v);
Bindings & bindings(*state->allocBindings(0));
auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v);

return state.forceString(*v2);
return state->forceString(*v2);
}
};

Expand Down

0 comments on commit 0629601

Please sign in to comment.