forked from lix-project/lix
Move EvalState from the stack to the heap
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.
This commit is contained in:
parent
c905d8b0a8
commit
0629601da1
|
@ -239,10 +239,10 @@ void mainWrapped(int argc, char * * argv)
|
||||||
|
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
|
|
||||||
EvalState state(myArgs.searchPath, store);
|
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
|
||||||
state.repair = repair;
|
state->repair = repair;
|
||||||
|
|
||||||
Bindings & autoArgs = *myArgs.getAutoArgs(state);
|
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
||||||
|
|
||||||
if (packages) {
|
if (packages) {
|
||||||
std::ostringstream joined;
|
std::ostringstream joined;
|
||||||
|
@ -268,7 +268,7 @@ void mainWrapped(int argc, char * * argv)
|
||||||
std::vector<Expr *> exprs;
|
std::vector<Expr *> exprs;
|
||||||
|
|
||||||
if (readStdin)
|
if (readStdin)
|
||||||
exprs = {state.parseStdin()};
|
exprs = {state->parseStdin()};
|
||||||
else
|
else
|
||||||
for (auto i : left) {
|
for (auto i : left) {
|
||||||
auto absolute = i;
|
auto absolute = i;
|
||||||
|
@ -276,13 +276,13 @@ void mainWrapped(int argc, char * * argv)
|
||||||
absolute = canonPath(absPath(i), true);
|
absolute = canonPath(absPath(i), true);
|
||||||
} catch (Error e) {};
|
} catch (Error e) {};
|
||||||
if (fromArgs)
|
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(!.*)?")))
|
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
|
else
|
||||||
/* If we're in a #! script, interpret filenames
|
/* If we're in a #! script, interpret filenames
|
||||||
relative to the script. */
|
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)))));
|
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,12 +291,12 @@ void mainWrapped(int argc, char * * argv)
|
||||||
|
|
||||||
for (auto e : exprs) {
|
for (auto e : exprs) {
|
||||||
Value vRoot;
|
Value vRoot;
|
||||||
state.eval(e, vRoot);
|
state->eval(e, vRoot);
|
||||||
|
|
||||||
for (auto & i : attrPaths) {
|
for (auto & i : attrPaths) {
|
||||||
Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot));
|
Value & v(*findAlongAttrPath(*state, i, autoArgs, vRoot));
|
||||||
state.forceValue(v);
|
state->forceValue(v);
|
||||||
getDerivations(state, v, "", autoArgs, drvs, false);
|
getDerivations(*state, v, "", autoArgs, drvs, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,12 +332,12 @@ void mainWrapped(int argc, char * * argv)
|
||||||
if (shell == "") {
|
if (shell == "") {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto expr = state.parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath("."));
|
auto expr = state->parseExprFromString("(import <nixpkgs> {}).bashInteractive", absPath("."));
|
||||||
|
|
||||||
Value v;
|
Value v;
|
||||||
state.eval(expr, v);
|
state->eval(expr, v);
|
||||||
|
|
||||||
auto drv = getDerivation(state, v, false);
|
auto drv = getDerivation(*state, v, false);
|
||||||
if (!drv)
|
if (!drv)
|
||||||
throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation");
|
throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation");
|
||||||
|
|
||||||
|
|
|
@ -158,16 +158,16 @@ int main(int argc, char * * argv)
|
||||||
|
|
||||||
auto store = openStore();
|
auto store = openStore();
|
||||||
|
|
||||||
EvalState state(myArgs.searchPath, store);
|
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
|
||||||
state.repair = repair;
|
state->repair = repair;
|
||||||
|
|
||||||
Bindings & autoArgs = *myArgs.getAutoArgs(state);
|
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
||||||
|
|
||||||
if (attrPaths.empty()) attrPaths = {""};
|
if (attrPaths.empty()) attrPaths = {""};
|
||||||
|
|
||||||
if (findFile) {
|
if (findFile) {
|
||||||
for (auto & i : files) {
|
for (auto & i : files) {
|
||||||
Path p = state.findFile(i);
|
Path p = state->findFile(i);
|
||||||
if (p == "") throw Error(format("unable to find '%1%'") % i);
|
if (p == "") throw Error(format("unable to find '%1%'") % i);
|
||||||
std::cout << p << std::endl;
|
std::cout << p << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -175,20 +175,20 @@ int main(int argc, char * * argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readStdin) {
|
if (readStdin) {
|
||||||
Expr * e = state.parseStdin();
|
Expr * e = state->parseStdin();
|
||||||
processExpr(state, attrPaths, parseOnly, strict, autoArgs,
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
||||||
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
||||||
} else if (files.empty() && !fromArgs)
|
} else if (files.empty() && !fromArgs)
|
||||||
files.push_back("./default.nix");
|
files.push_back("./default.nix");
|
||||||
|
|
||||||
for (auto & i : files) {
|
for (auto & i : files) {
|
||||||
Expr * e = fromArgs
|
Expr * e = fromArgs
|
||||||
? state.parseExprFromString(i, absPath("."))
|
? state->parseExprFromString(i, absPath("."))
|
||||||
: state.parseExprFromFile(resolveExprPath(state.checkSourcePath(lookupFileArg(state, i))));
|
: state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i))));
|
||||||
processExpr(state, attrPaths, parseOnly, strict, autoArgs,
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
||||||
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.printStats();
|
state->printStats();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,9 +95,9 @@ int main(int argc, char * * argv)
|
||||||
throw UsageError("too many arguments");
|
throw UsageError("too many arguments");
|
||||||
|
|
||||||
auto store = openStore();
|
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
|
/* If -A is given, get the URI from the specified Nix
|
||||||
expression. */
|
expression. */
|
||||||
|
@ -107,33 +107,33 @@ int main(int argc, char * * argv)
|
||||||
throw UsageError("you must specify a URI");
|
throw UsageError("you must specify a URI");
|
||||||
uri = args[0];
|
uri = args[0];
|
||||||
} else {
|
} else {
|
||||||
Path path = resolveExprPath(lookupFileArg(state, args.empty() ? "." : args[0]));
|
Path path = resolveExprPath(lookupFileArg(*state, args.empty() ? "." : args[0]));
|
||||||
Value vRoot;
|
Value vRoot;
|
||||||
state.evalFile(path, vRoot);
|
state->evalFile(path, vRoot);
|
||||||
Value & v(*findAlongAttrPath(state, attrPath, autoArgs, vRoot));
|
Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot));
|
||||||
state.forceAttrs(v);
|
state->forceAttrs(v);
|
||||||
|
|
||||||
/* Extract the URI. */
|
/* 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())
|
if (attr == v.attrs->end())
|
||||||
throw Error("attribute set does not contain a 'urls' attribute");
|
throw Error("attribute set does not contain a 'urls' attribute");
|
||||||
state.forceList(*attr->value);
|
state->forceList(*attr->value);
|
||||||
if (attr->value->listSize() < 1)
|
if (attr->value->listSize() < 1)
|
||||||
throw Error("'urls' list is empty");
|
throw Error("'urls' list is empty");
|
||||||
uri = state.forceString(*attr->value->listElems()[0]);
|
uri = state->forceString(*attr->value->listElems()[0]);
|
||||||
|
|
||||||
/* Extract the hash mode. */
|
/* 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())
|
if (attr == v.attrs->end())
|
||||||
printInfo("warning: this does not look like a fetchurl call");
|
printInfo("warning: this does not look like a fetchurl call");
|
||||||
else
|
else
|
||||||
unpack = state.forceString(*attr->value) == "recursive";
|
unpack = state->forceString(*attr->value) == "recursive";
|
||||||
|
|
||||||
/* Extract the name. */
|
/* Extract the name. */
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
attr = v.attrs->find(state.symbols.create("name"));
|
attr = v.attrs->find(state->symbols.create("name"));
|
||||||
if (attr != v.attrs->end())
|
if (attr != v.attrs->end())
|
||||||
name = state.forceString(*attr->value);
|
name = state->forceString(*attr->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ int main(int argc, char * * argv)
|
||||||
|
|
||||||
if (storePath.empty()) {
|
if (storePath.empty()) {
|
||||||
|
|
||||||
auto actualUri = resolveMirrorUri(state, uri);
|
auto actualUri = resolveMirrorUri(*state, uri);
|
||||||
|
|
||||||
/* Download the file. */
|
/* Download the file. */
|
||||||
DownloadRequest req(actualUri);
|
DownloadRequest req(actualUri);
|
||||||
|
|
|
@ -693,8 +693,8 @@ struct CmdRepl : StoreCommand, MixEvalArgs
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
NixRepl repl(searchPath, openStore());
|
auto repl = std::make_unique<NixRepl>(searchPath, openStore());
|
||||||
repl.mainLoop(files);
|
repl->mainLoop(files);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 req = DownloadRequest("https://github.com/NixOS/nixpkgs/raw/master/nixos/modules/installer/tools/nix-fallback-paths.nix");
|
||||||
auto res = getDownloader()->download(req);
|
auto res = getDownloader()->download(req);
|
||||||
|
|
||||||
EvalState state(Strings(), store);
|
auto state = std::make_unique<EvalState>(Strings(), store);
|
||||||
auto v = state.allocValue();
|
auto v = state->allocValue();
|
||||||
state.eval(state.parseExprFromString(*res.data, "/no-such-path"), *v);
|
state->eval(state->parseExprFromString(*res.data, "/no-such-path"), *v);
|
||||||
Bindings & bindings(*state.allocBindings(0));
|
Bindings & bindings(*state->allocBindings(0));
|
||||||
auto v2 = findAlongAttrPath(state, settings.thisSystem, bindings, *v);
|
auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v);
|
||||||
|
|
||||||
return state.forceString(*v2);
|
return state->forceString(*v2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue