1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-26 04:00:59 +01:00

Add a session independent cache.

This commit is contained in:
Nicolas Pierron 2009-07-08 09:26:15 +00:00
parent 7244b9b861
commit 4941ba3413
3 changed files with 36 additions and 7 deletions

View file

@ -16,9 +16,9 @@ namespace nix {
EvalState::EvalState() EvalState::EvalState()
: normalForms(32768), primOps(128) : sessionNormalForms(32768), normalForms(32768), primOps(128)
{ {
nrEvaluated = nrCached = 0; nrEvaluated = nrCached = nrDephtAfterReset = 0;
initNixExprHelpers(); initNixExprHelpers();
@ -803,10 +803,17 @@ Expr evalExpr(EvalState & state, Expr e)
#endif #endif
state.nrEvaluated++; state.nrEvaluated++;
state.nrDephtAfterReset++;
/* Consult the memo table to quickly get the normal form of /* Consult the memo table to quickly get the normal form of
previously evaluated expressions. */ previously evaluated expressions. */
Expr nf = state.normalForms.get(e); Expr nf = state.normalForms.get(e);
if (nf) {
state.nrCached++;
return nf;
}
nf = state.sessionNormalForms.get(e);
if (nf) { if (nf) {
if (nf == makeBlackHole()) if (nf == makeBlackHole())
throwEvalError("infinite recursion encountered"); throwEvalError("infinite recursion encountered");
@ -815,14 +822,22 @@ Expr evalExpr(EvalState & state, Expr e)
} }
/* Otherwise, evaluate and memoize. */ /* Otherwise, evaluate and memoize. */
state.normalForms.set(e, makeBlackHole()); state.sessionNormalForms.set(e, makeBlackHole());
try { try {
nf = evalExpr2(state, e); nf = evalExpr2(state, e);
} catch (Error & err) { } catch (Error & err) {
state.normalForms.remove(e); state.sessionNormalForms.remove(e);
throw; throw;
} }
if (state.nrDephtAfterReset) {
state.sessionNormalForms.remove(e);
state.normalForms.set(e, nf); state.normalForms.set(e, nf);
state.nrDephtAfterReset--;
} else {
state.sessionNormalForms.set(e, nf);
}
return nf; return nf;
} }
@ -830,6 +845,7 @@ Expr evalExpr(EvalState & state, Expr e)
Expr evalFile(EvalState & state, const Path & path) Expr evalFile(EvalState & state, const Path & path)
{ {
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
state.nrDephtAfterReset = 0;
Expr e = parseExprFromFile(state, path); Expr e = parseExprFromFile(state, path);
try { try {
return evalExpr(state, e); return evalExpr(state, e);
@ -901,11 +917,13 @@ void printEvalStats(EvalState & state)
char x; char x;
bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0"; bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0";
printMsg(showStats ? lvlInfo : lvlDebug, printMsg(showStats ? lvlInfo : lvlDebug,
format("evaluated %1% expressions, %2% cache hits, %3%%% efficiency, used %4% ATerm bytes, used %5% bytes of stack space") format("evaluated %1% expressions, %2% cache hits, %3%%% efficiency, used %4% ATerm bytes, used %5% bytes of stack space, %6% normal reduction, %7% session dependent reduction.")
% state.nrEvaluated % state.nrCached % state.nrEvaluated % state.nrCached
% ((float) state.nrCached / (float) state.nrEvaluated * 100) % ((float) state.nrCached / (float) state.nrEvaluated * 100)
% AT_calcAllocatedSize() % AT_calcAllocatedSize()
% (&x - deepestStack)); % (&x - deepestStack)
% state.normalForms.size()
% state.sessionNormalForms.size());
if (showStats) if (showStats)
printATermMapStats(); printATermMapStats();
} }

View file

@ -29,6 +29,7 @@ typedef Expr (* PrimOp) (EvalState &, const ATermVector & args);
struct EvalState struct EvalState
{ {
ATermMap sessionNormalForms;
ATermMap normalForms; ATermMap normalForms;
ATermMap primOps; ATermMap primOps;
DrvRoots drvRoots; DrvRoots drvRoots;
@ -37,6 +38,7 @@ struct EvalState
unsigned int nrEvaluated; unsigned int nrEvaluated;
unsigned int nrCached; unsigned int nrCached;
unsigned int nrDephtAfterReset;
bool allowUnsafeEquality; bool allowUnsafeEquality;

View file

@ -74,12 +74,14 @@ static Expr prim_null(EvalState & state, const ATermVector & args)
platforms. */ platforms. */
static Expr prim_currentSystem(EvalState & state, const ATermVector & args) static Expr prim_currentSystem(EvalState & state, const ATermVector & args)
{ {
state.nrDephtAfterReset = 0;
return makeStr(thisSystem); return makeStr(thisSystem);
} }
static Expr prim_currentTime(EvalState & state, const ATermVector & args) static Expr prim_currentTime(EvalState & state, const ATermVector & args)
{ {
state.nrDephtAfterReset = 0;
return ATmake("Int(<int>)", time(0)); return ATmake("Int(<int>)", time(0));
} }
@ -228,6 +230,7 @@ static Expr prim_addErrorContext(EvalState & state, const ATermVector & args)
static Expr prim_getEnv(EvalState & state, const ATermVector & args) static Expr prim_getEnv(EvalState & state, const ATermVector & args)
{ {
string name = evalStringNoCtx(state, args[0]); string name = evalStringNoCtx(state, args[0]);
state.nrDephtAfterReset = 0;
return makeStr(getEnv(name)); return makeStr(getEnv(name));
} }
@ -316,6 +319,7 @@ static Hash hashDerivationModulo(EvalState & state, Derivation drv)
static Expr prim_derivationStrict(EvalState & state, const ATermVector & args) static Expr prim_derivationStrict(EvalState & state, const ATermVector & args)
{ {
startNest(nest, lvlVomit, "evaluating derivation"); startNest(nest, lvlVomit, "evaluating derivation");
state.nrDephtAfterReset = 0;
ATermMap attrs; ATermMap attrs;
queryAllAttrs(evalExpr(state, args[0]), attrs, true); queryAllAttrs(evalExpr(state, args[0]), attrs, true);
@ -549,6 +553,7 @@ static Expr prim_storePath(EvalState & state, const ATermVector & args)
{ {
PathSet context; PathSet context;
Path path = canonPath(coerceToPath(state, args[0], context)); Path path = canonPath(coerceToPath(state, args[0], context));
state.nrDephtAfterReset = 0;
if (!isInStore(path)) if (!isInStore(path))
throw EvalError(format("path `%1%' is not in the Nix store") % path); throw EvalError(format("path `%1%' is not in the Nix store") % path);
Path path2 = toStorePath(path); Path path2 = toStorePath(path);
@ -565,6 +570,7 @@ static Expr prim_pathExists(EvalState & state, const ATermVector & args)
Path path = coerceToPath(state, args[0], context); Path path = coerceToPath(state, args[0], context);
if (!context.empty()) if (!context.empty())
throw EvalError(format("string `%1%' cannot refer to other paths") % path); throw EvalError(format("string `%1%' cannot refer to other paths") % path);
state.nrDephtAfterReset = 0;
return makeBool(pathExists(path)); return makeBool(pathExists(path));
} }
@ -598,6 +604,7 @@ static Expr prim_readFile(EvalState & state, const ATermVector & args)
Path path = coerceToPath(state, args[0], context); Path path = coerceToPath(state, args[0], context);
if (!context.empty()) if (!context.empty())
throw EvalError(format("string `%1%' cannot refer to other paths") % path); throw EvalError(format("string `%1%' cannot refer to other paths") % path);
state.nrDephtAfterReset = 0;
return makeStr(readFile(path)); return makeStr(readFile(path));
} }
@ -637,6 +644,7 @@ static Expr prim_toFile(EvalState & state, const ATermVector & args)
refs.insert(path); refs.insert(path);
} }
state.nrDephtAfterReset = 0;
Path storePath = readOnlyMode Path storePath = readOnlyMode
? computeStorePathForText(name, contents, refs) ? computeStorePathForText(name, contents, refs)
: store->addTextToStore(name, contents, refs); : store->addTextToStore(name, contents, refs);
@ -689,6 +697,7 @@ static Expr prim_filterSource(EvalState & state, const ATermVector & args)
FilterFromExpr filter(state, args[0]); FilterFromExpr filter(state, args[0]);
state.nrDephtAfterReset = 0;
Path dstPath = readOnlyMode Path dstPath = readOnlyMode
? computeStorePathForPath(path, true, htSHA256, filter).first ? computeStorePathForPath(path, true, htSHA256, filter).first
: store->addToStore(path, true, htSHA256, filter); : store->addToStore(path, true, htSHA256, filter);