libexpr: remove eval caches from EvalState
eval caches are not used by actual eval at all, only by the flake-shaped
wrappers around evaluation. moving caches into a subclass both clarifies
that eval caches and eval states are coupled and separates concerns that
should not have been intermixed as they were here. in the future we will
want to split up and decouple things even further. that'll have to wait.
Change-Id: I7b69510c0f8b212f05fae62e7b992d9475b4841f
This commit is contained in:
parent
564f464772
commit
7c650ea241
|
@ -102,15 +102,15 @@ ref<Store> EvalCommand::getEvalStore()
|
|||
return ref<Store>(evalStore);
|
||||
}
|
||||
|
||||
ref<EvalState> EvalCommand::getEvalState()
|
||||
ref<eval_cache::CachingEvalState> EvalCommand::getEvalState()
|
||||
{
|
||||
if (!evalState) {
|
||||
evalState =
|
||||
#if HAVE_BOEHMGC
|
||||
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(),
|
||||
std::allocate_shared<eval_cache::CachingEvalState>(traceable_allocator<EvalState>(),
|
||||
searchPath, getEvalStore(), getStore())
|
||||
#else
|
||||
std::make_shared<EvalState>(
|
||||
std::make_shared<eval_cache::CachingEvalState>(
|
||||
searchPath, getEvalStore(), getStore())
|
||||
#endif
|
||||
;
|
||||
|
@ -121,7 +121,7 @@ ref<EvalState> EvalCommand::getEvalState()
|
|||
evalState->debug = std::make_unique<DebugState>(&AbstractNixRepl::runSimple);
|
||||
};
|
||||
}
|
||||
return ref<EvalState>(evalState);
|
||||
return ref<eval_cache::CachingEvalState>(evalState);
|
||||
}
|
||||
|
||||
MixOperateOnOptions::MixOperateOnOptions()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
///@file
|
||||
|
||||
#include "lix/libcmd/installable-value.hh"
|
||||
#include "lix/libexpr/eval-cache.hh"
|
||||
#include "lix/libutil/args.hh"
|
||||
#include "lix/libcmd/common-eval-args.hh"
|
||||
#include "lix/libstore/path.hh"
|
||||
|
@ -76,12 +77,12 @@ struct EvalCommand : virtual StoreCommand, MixEvalArgs
|
|||
|
||||
ref<Store> getEvalStore();
|
||||
|
||||
ref<EvalState> getEvalState();
|
||||
ref<eval_cache::CachingEvalState> getEvalState();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Store> evalStore;
|
||||
|
||||
std::shared_ptr<EvalState> evalState;
|
||||
std::shared_ptr<eval_cache::CachingEvalState> evalState;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -331,7 +332,7 @@ void completeFlakeRef(AddCompletions & completions, ref<Store> store, std::strin
|
|||
|
||||
void completeFlakeRefWithFragment(
|
||||
AddCompletions & completions,
|
||||
ref<EvalState> evalState,
|
||||
ref<eval_cache::CachingEvalState> evalState,
|
||||
flake::LockFlags lockFlags,
|
||||
Strings attrPathPrefixes,
|
||||
const Strings & defaultFlakeAttrPaths,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
namespace nix {
|
||||
|
||||
InstallableAttrPath::InstallableAttrPath(
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
const std::string & attrPath,
|
||||
|
@ -93,7 +93,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
|
|||
}
|
||||
|
||||
InstallableAttrPath InstallableAttrPath::parse(
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
std::string_view prefix,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
///@file
|
||||
|
||||
#include "lix/libcmd/installable-value.hh"
|
||||
#include "lix/libexpr/eval-cache.hh"
|
||||
#include "lix/libstore/outputs-spec.hh"
|
||||
#include "lix/libcmd/command.hh"
|
||||
#include "lix/libcmd/common-eval-args.hh"
|
||||
|
@ -19,7 +20,7 @@ class InstallableAttrPath : public InstallableValue
|
|||
ExtendedOutputsSpec extendedOutputsSpec;
|
||||
|
||||
InstallableAttrPath(
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
const std::string & attrPath,
|
||||
|
@ -34,7 +35,7 @@ class InstallableAttrPath : public InstallableValue
|
|||
public:
|
||||
|
||||
static InstallableAttrPath parse(
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
std::string_view prefix,
|
||||
|
|
|
@ -67,7 +67,7 @@ static std::string showAttrPaths(const std::vector<std::string> & paths)
|
|||
|
||||
InstallableFlake::InstallableFlake(
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
std::string_view fragment,
|
||||
ExtendedOutputsSpec extendedOutputsSpec,
|
||||
|
|
|
@ -40,7 +40,7 @@ struct InstallableFlake : InstallableValue
|
|||
|
||||
InstallableFlake(
|
||||
SourceExprCommand * cmd,
|
||||
ref<EvalState> state,
|
||||
ref<eval_cache::CachingEvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
std::string_view fragment,
|
||||
ExtendedOutputsSpec extendedOutputsSpec,
|
||||
|
@ -83,7 +83,7 @@ static inline FlakeRef defaultNixpkgsFlakeRef()
|
|||
}
|
||||
|
||||
ref<eval_cache::EvalCache> openEvalCache(
|
||||
EvalState & state,
|
||||
eval_cache::CachingEvalState & state,
|
||||
std::shared_ptr<flake::LockedFlake> lockedFlake);
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
///@file
|
||||
|
||||
#include "lix/libcmd/installables.hh"
|
||||
#include "lix/libexpr/eval-cache.hh"
|
||||
#include "lix/libexpr/flake/flake.hh"
|
||||
|
||||
namespace nix {
|
||||
|
@ -9,8 +10,6 @@ namespace nix {
|
|||
struct DrvInfo;
|
||||
struct SourceExprCommand;
|
||||
|
||||
namespace eval_cache { class EvalCache; class AttrCursor; }
|
||||
|
||||
struct App
|
||||
{
|
||||
std::vector<DerivedPath> context;
|
||||
|
@ -71,9 +70,9 @@ struct ExtraPathInfoValue : ExtraPathInfo
|
|||
*/
|
||||
struct InstallableValue : Installable
|
||||
{
|
||||
ref<EvalState> state;
|
||||
ref<eval_cache::CachingEvalState> state;
|
||||
|
||||
InstallableValue(ref<EvalState> state) : state(state) {}
|
||||
InstallableValue(ref<eval_cache::CachingEvalState> state) : state(state) {}
|
||||
|
||||
virtual ~InstallableValue() { }
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
|
|||
|
||||
void completeFlakeRefWithFragment(
|
||||
AddCompletions & completions,
|
||||
ref<EvalState> evalState,
|
||||
ref<eval_cache::CachingEvalState> evalState,
|
||||
flake::LockFlags lockFlags,
|
||||
Strings attrPathPrefixes,
|
||||
const Strings & defaultFlakeAttrPaths,
|
||||
|
@ -390,7 +390,7 @@ static StorePath getDeriver(
|
|||
}
|
||||
|
||||
ref<eval_cache::EvalCache> openEvalCache(
|
||||
EvalState & state,
|
||||
eval_cache::CachingEvalState & state,
|
||||
std::shared_ptr<flake::LockedFlake> lockedFlake)
|
||||
{
|
||||
auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval
|
||||
|
@ -415,11 +415,7 @@ ref<eval_cache::EvalCache> openEvalCache(
|
|||
};
|
||||
|
||||
if (fingerprint) {
|
||||
auto search = state.evalCaches.find(fingerprint.value());
|
||||
if (search == state.evalCaches.end()) {
|
||||
search = state.evalCaches.emplace(fingerprint.value(), make_ref<nix::eval_cache::EvalCache>(fingerprint, state, rootLoader)).first;
|
||||
}
|
||||
return search->second;
|
||||
return state.getCacheFor(fingerprint.value(), rootLoader);
|
||||
} else {
|
||||
return make_ref<nix::eval_cache::EvalCache>(std::nullopt, state, rootLoader);
|
||||
}
|
||||
|
|
|
@ -334,6 +334,16 @@ static std::shared_ptr<AttrDb> makeAttrDb(
|
|||
}
|
||||
}
|
||||
|
||||
ref<EvalCache> CachingEvalState::getCacheFor(Hash hash, RootLoader rootLoader)
|
||||
{
|
||||
if (auto it = caches.find(hash); it != caches.end()) {
|
||||
return it->second;
|
||||
}
|
||||
auto cache = make_ref<EvalCache>(hash, *this, rootLoader);
|
||||
caches.emplace(hash, cache);
|
||||
return cache;
|
||||
}
|
||||
|
||||
EvalCache::EvalCache(
|
||||
std::optional<std::reference_wrapper<const Hash>> useCache,
|
||||
EvalState & state,
|
||||
|
|
|
@ -13,13 +13,34 @@ namespace nix::eval_cache {
|
|||
struct AttrDb;
|
||||
class AttrCursor;
|
||||
|
||||
typedef std::function<Value *()> RootLoader;
|
||||
|
||||
/**
|
||||
* EvalState with caching support. Historically this was part of EvalState,
|
||||
* but it was split out to make maintenance easier. This could've been just
|
||||
* a pair of EvalState and the cache map, but doing so would currently hide
|
||||
* the rather strong connection between EvalState and these caches. At some
|
||||
* future time the cache interface should be changed to hide its EvalState.
|
||||
*/
|
||||
class CachingEvalState : public EvalState
|
||||
{
|
||||
/**
|
||||
* A cache for evaluation caches, so as to reuse the same root value if possible
|
||||
*/
|
||||
std::map<Hash, ref<EvalCache>> caches;
|
||||
|
||||
public:
|
||||
using EvalState::EvalState;
|
||||
|
||||
ref<EvalCache> getCacheFor(Hash hash, RootLoader rootLoader);
|
||||
};
|
||||
|
||||
class EvalCache : public std::enable_shared_from_this<EvalCache>
|
||||
{
|
||||
friend class AttrCursor;
|
||||
|
||||
std::shared_ptr<AttrDb> db;
|
||||
EvalState & state;
|
||||
typedef std::function<Value *()> RootLoader;
|
||||
RootLoader rootLoader;
|
||||
RootValue value;
|
||||
|
||||
|
|
|
@ -321,11 +321,6 @@ public:
|
|||
return *new EvalErrorBuilder<T>(*this, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* A cache for evaluation caches, so as to reuse the same root value if possible
|
||||
*/
|
||||
std::map<const Hash, ref<eval_cache::EvalCache>> evalCaches;
|
||||
|
||||
private:
|
||||
|
||||
/* Cache for calls to addToStore(); maps source paths to the store
|
||||
|
|
Loading…
Reference in a new issue