1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-30 06:01:00 +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 std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
{ {
// FIXME: cache the accessor
if (!scheme) if (!scheme)
throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs())); throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs()));
try { try {
auto [accessor, final] = scheme->getAccessor(store, *this); auto [accessor, final] = scheme->getAccessor(store, *this);
accessor->fingerprint = scheme->getFingerprint(store, *this);
checkLocks(final); checkLocks(final);
return {accessor, std::move(final)}; return {accessor, std::move(final)};
} catch (Error & e) { } catch (Error & e) {
@ -256,10 +259,7 @@ std::optional<time_t> Input::getLastModified() const
std::optional<std::string> Input::getFingerprint(ref<Store> store) const std::optional<std::string> Input::getFingerprint(ref<Store> store) const
{ {
if (auto rev = getRev()) return scheme ? scheme->getFingerprint(store, *this) : std::nullopt;
return rev->gitRev();
assert(scheme);
return scheme->getFingerprint(store, *this);
} }
ParsedURL InputScheme::toURL(const Input & input) const 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()); 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 virtual std::optional<CanonPath> isRelative(const Input & input) const
{ return std::nullopt; } { return std::nullopt; }
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const;
{ return std::nullopt; }
}; };
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher); void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);

View file

@ -1,6 +1,7 @@
#include "input-accessor.hh" #include "input-accessor.hh"
#include "util.hh" #include "util.hh"
#include "store-api.hh" #include "store-api.hh"
#include "cache.hh"
#include <atomic> #include <atomic>
@ -96,6 +97,21 @@ StorePath InputAccessor::fetchToStore(
// FIXME: add an optimisation for the case where the accessor is // FIXME: add an optimisation for the case where the accessor is
// an FSInputAccessor pointing to a store path. // 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) { auto source = sinkToSource([&](Sink & sink) {
dumpPath(path, sink, filter ? *filter : defaultPathFilter); dumpPath(path, sink, filter ? *filter : defaultPathFilter);
}); });
@ -105,6 +121,9 @@ StorePath InputAccessor::fetchToStore(
? store->computeStorePathFromDump(*source, name).first ? store->computeStorePathFromDump(*source, name).first
: store->addToStoreFromDump(*source, name, FileIngestionMethod::Recursive, htSHA256, repair); : store->addToStoreFromDump(*source, name, FileIngestionMethod::Recursive, htSHA256, repair);
if (cacheKey)
fetchers::getCache()->upsertFact(*cacheKey, store->printStorePath(storePath));
return storePath; return storePath;
} }

View file

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