Make the file cache keyed on SourcePath

This commit is contained in:
Eelco Dolstra 2022-05-12 16:48:22 +02:00
parent bc57bd2202
commit cd893a22f5
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
7 changed files with 28 additions and 47 deletions

View file

@ -1,7 +1,7 @@
{ command, renderLinks ? false }: { command, renderLinks ? false }:
with builtins; with builtins;
with import ./utils.nix; with import <nix/utils.nix>;
let let

View file

@ -20,7 +20,7 @@ dummy-env = env -i \
NIX_STATE_DIR=/dummy \ NIX_STATE_DIR=/dummy \
NIX_CONFIG='cores = 0' NIX_CONFIG='cores = 0'
nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw nix-eval = $(dummy-env) $(bindir)/nix eval --experimental-features nix-command -I nix=doc/manual --store dummy:// --impure --raw
$(d)/%.1: $(d)/src/command-ref/%.md $(d)/%.1: $(d)/src/command-ref/%.md
@printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp @printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp

View file

@ -1010,17 +1010,14 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env)
void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial) void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
{ {
// FIXME: use SourcePath as cache key
auto pathKey = path.to_string();
FileEvalCache::iterator i; FileEvalCache::iterator i;
if ((i = fileEvalCache.find(pathKey)) != fileEvalCache.end()) { if ((i = fileEvalCache.find(path)) != fileEvalCache.end()) {
v = i->second; v = i->second;
return; return;
} }
auto resolvedPath = resolveExprPath(path); auto resolvedPath = resolveExprPath(path);
auto resolvedPathKey = resolvedPath.to_string(); if ((i = fileEvalCache.find(resolvedPath)) != fileEvalCache.end()) {
if ((i = fileEvalCache.find(resolvedPathKey)) != fileEvalCache.end()) {
v = i->second; v = i->second;
return; return;
} }
@ -1028,7 +1025,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
printTalkative("evaluating file '%1%'", resolvedPath); printTalkative("evaluating file '%1%'", resolvedPath);
Expr * e = nullptr; Expr * e = nullptr;
auto j = fileParseCache.find(resolvedPathKey); auto j = fileParseCache.find(resolvedPath);
if (j != fileParseCache.end()) if (j != fileParseCache.end())
e = j->second; e = j->second;
@ -1038,24 +1035,6 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
e = parseExprFromFile(checkSourcePath(resolvedPath)); e = parseExprFromFile(checkSourcePath(resolvedPath));
#endif #endif
cacheFile(pathKey, resolvedPathKey, e, v, mustBeTrivial);
}
void EvalState::resetFileCache()
{
fileEvalCache.clear();
fileParseCache.clear();
}
void EvalState::cacheFile(
const Path & path,
const Path & resolvedPath,
Expr * e,
Value & v,
bool mustBeTrivial)
{
fileParseCache[resolvedPath] = e; fileParseCache[resolvedPath] = e;
try { try {
@ -1066,7 +1045,7 @@ void EvalState::cacheFile(
throw EvalError("file '%s' must be an attribute set", path); throw EvalError("file '%s' must be an attribute set", path);
eval(e, v); eval(e, v);
} catch (Error & e) { } catch (Error & e) {
addErrorTrace(e, "while evaluating the file '%1%':", resolvedPath); addErrorTrace(e, "while evaluating the file '%1%':", resolvedPath.to_string());
throw; throw;
} }
@ -1075,6 +1054,13 @@ void EvalState::cacheFile(
} }
void EvalState::resetFileCache()
{
fileEvalCache.clear();
fileParseCache.clear();
}
void EvalState::eval(Expr * e, Value & v) void EvalState::eval(Expr * e, Value & v)
{ {
e->eval(*this, baseEnv, v); e->eval(*this, baseEnv, v);

View file

@ -116,17 +116,17 @@ private:
/* A cache from path names to parse trees. */ /* A cache from path names to parse trees. */
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
typedef std::map<Path, Expr *, std::less<Path>, traceable_allocator<std::pair<const Path, Expr *> > > FileParseCache; typedef std::map<SourcePath, Expr *, std::less<SourcePath>, traceable_allocator<std::pair<const SourcePath, Expr *>>> FileParseCache;
#else #else
typedef std::map<Path, Expr *> FileParseCache; typedef std::map<SourcePath, Expr *> FileParseCache;
#endif #endif
FileParseCache fileParseCache; FileParseCache fileParseCache;
/* A cache from path names to values. */ /* A cache from path names to values. */
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
typedef std::map<Path, Value, std::less<Path>, traceable_allocator<std::pair<const Path, Value> > > FileEvalCache; typedef std::map<SourcePath, Value, std::less<SourcePath>, traceable_allocator<std::pair<const SourcePath, Value> >> FileEvalCache;
#else #else
typedef std::map<Path, Value> FileEvalCache; typedef std::map<SourcePath, Value> FileEvalCache;
#endif #endif
FileEvalCache fileEvalCache; FileEvalCache fileEvalCache;
@ -200,14 +200,6 @@ public:
trivial (i.e. doesn't require arbitrary computation). */ trivial (i.e. doesn't require arbitrary computation). */
void evalFile(const SourcePath & path, Value & v, bool mustBeTrivial = false); void evalFile(const SourcePath & path, Value & v, bool mustBeTrivial = false);
/* Like `cacheFile`, but with an already parsed expression. */
void cacheFile(
const Path & path,
const Path & resolvedPath,
Expr * e,
Value & v,
bool mustBeTrivial = false);
void resetFileCache(); void resetFileCache();
/* Look up a file in the search path. */ /* Look up a file in the search path. */

View file

@ -183,6 +183,7 @@ struct FSInputAccessorImpl : FSInputAccessor
return false; return false;
if (allowedPaths) { if (allowedPaths) {
#if 0
// FIXME: this can be done more efficiently. // FIXME: this can be done more efficiently.
auto p = (std::string) absPath.substr(root.size()); auto p = (std::string) absPath.substr(root.size());
if (p == "") p = "/"; if (p == "") p = "/";
@ -193,6 +194,7 @@ struct FSInputAccessorImpl : FSInputAccessor
return false; return false;
p = dirOf(p); p = dirOf(p);
} }
#endif
} }
return true; return true;

View file

@ -113,6 +113,11 @@ struct SourcePath
return std::tie(accessor, path) == std::tie(x.accessor, x.path); return std::tie(accessor, path) == std::tie(x.accessor, x.path);
} }
bool operator != (const SourcePath & x) const
{
return std::tie(accessor, path) != std::tie(x.accessor, x.path);
}
bool operator < (const SourcePath & x) const bool operator < (const SourcePath & x) const
{ {
return std::tie(accessor, path) < std::tie(x.accessor, x.path); return std::tie(accessor, path) < std::tie(x.accessor, x.path);

View file

@ -178,14 +178,10 @@ static void showHelp(std::vector<std::string> subcommand, MultiCommand & topleve
#include "generate-manpage.nix.gen.hh" #include "generate-manpage.nix.gen.hh"
, "/"), *vGenerateManpage); , "/"), *vGenerateManpage);
// FIXME: use MemoryAccessor state.corepkgsFS->addFile(
auto vUtils = state.allocValue(); "/utils.nix",
state.cacheFile( #include "utils.nix.gen.hh"
"/utils.nix", "/utils.nix", );
state.parseExprFromString(
#include "utils.nix.gen.hh"
, "/"),
*vUtils);
auto attrs = state.buildBindings(16); auto attrs = state.buildBindings(16);
attrs.alloc("command").mkString(toplevel.toJSON().dump()); attrs.alloc("command").mkString(toplevel.toJSON().dump());