1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-29 21:50:58 +01:00

Persistently cache InputAccessor::fetchToStore()

This especially speeds up repeated evaluations that copy a large
source tree (e.g. 'nix.nixPath = [ "nixpkgs=${nixpkgs}" ];').
This commit is contained in:
Eelco Dolstra 2022-08-11 20:34:27 +02:00
parent 2e0d63caf6
commit beac2e67cd
4 changed files with 34 additions and 6 deletions

View file

@ -160,11 +160,14 @@ void Input::checkLocks(Input & input) const
std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
{
// FIXME: cache the accessor
if (!scheme)
throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs()));
try {
auto [accessor, final] = scheme->getAccessor(store, *this);
accessor->fingerprint = scheme->getFingerprint(store, *this);
checkLocks(final);
return {accessor, std::move(final)};
} catch (Error & e) {
@ -256,10 +259,7 @@ std::optional<time_t> Input::getLastModified() const
std::optional<std::string> Input::getFingerprint(ref<Store> store) const
{
if (auto rev = getRev())
return rev->gitRev();
assert(scheme);
return scheme->getFingerprint(store, *this);
return scheme ? scheme->getFingerprint(store, *this) : std::nullopt;
}
ParsedURL InputScheme::toURL(const Input & input) const
@ -293,4 +293,12 @@ void InputScheme::clone(const Input & input, const Path & destDir) const
throw Error("do not know how to clone input '%s'", input.to_string());
}
std::optional<std::string> InputScheme::getFingerprint(ref<Store> store, const Input & input) const
{
if (auto rev = input.getRev())
return rev->gitRev();
else
return std::nullopt;
}
}

View file

@ -141,8 +141,7 @@ struct InputScheme
virtual std::optional<CanonPath> isRelative(const Input & input) const
{ return std::nullopt; }
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const
{ return std::nullopt; }
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const;
};
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);

View file

@ -1,6 +1,7 @@
#include "input-accessor.hh"
#include "util.hh"
#include "store-api.hh"
#include "cache.hh"
#include <atomic>
@ -96,6 +97,21 @@ StorePath InputAccessor::fetchToStore(
// FIXME: add an optimisation for the case where the accessor is
// an FSInputAccessor pointing to a store path.
std::optional<std::string> cacheKey;
if (!filter && fingerprint) {
cacheKey = *fingerprint + "|" + name + "|" + path.abs();
if (auto storePathS = fetchers::getCache()->queryFact(*cacheKey)) {
if (auto storePath = store->maybeParseStorePath(*storePathS)) {
if (store->isValidPath(*storePath)) {
debug("store path cache hit for '%s'", showPath(path));
return *storePath;
}
}
}
} else
debug("source path '%s' is uncacheable", showPath(path));
auto source = sinkToSource([&](Sink & sink) {
dumpPath(path, sink, filter ? *filter : defaultPathFilter);
});
@ -105,6 +121,9 @@ StorePath InputAccessor::fetchToStore(
? store->computeStorePathFromDump(*source, name).first
: store->addToStoreFromDump(*source, name, FileIngestionMethod::Recursive, htSHA256, repair);
if (cacheKey)
fetchers::getCache()->upsertFact(*cacheKey, store->printStorePath(storePath));
return storePath;
}

View file

@ -21,6 +21,8 @@ struct InputAccessor : public std::enable_shared_from_this<InputAccessor>
std::string displayPrefix, displaySuffix;
std::optional<std::string> fingerprint;
InputAccessor();
virtual ~InputAccessor()