From 7ba933e989b9baf56c2b542c7788b38f6d9ccb50 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Dec 2024 13:56:03 +0100 Subject: [PATCH] Cache calls to GitRepo::getWorkdirInfo() A command like `nix flake metadata` was causing about 4 calls to getWorkdirInfo(), which is slow for large repos (even when they're not dirty). --- src/libfetchers/git-utils.cc | 14 ++++++++++++++ src/libfetchers/git-utils.hh | 2 ++ src/libfetchers/git.cc | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libfetchers/git-utils.cc b/src/libfetchers/git-utils.cc index bd5786857..15fa540b3 100644 --- a/src/libfetchers/git-utils.cc +++ b/src/libfetchers/git-utils.cc @@ -5,6 +5,7 @@ #include "signals.hh" #include "users.hh" #include "fs-sink.hh" +#include "sync.hh" #include #include @@ -1276,4 +1277,17 @@ ref getTarballCache() return GitRepo::openRepo(repoDir, true, true); } +GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path & path) +{ + static Sync> _cache; + { + auto cache(_cache.lock()); + auto i = cache->find(path); + if (i != cache->end()) return i->second; + } + auto workdirInfo = GitRepo::openRepo(path)->getWorkdirInfo(); + _cache.lock()->emplace(path, workdirInfo); + return workdirInfo; +} + } diff --git a/src/libfetchers/git-utils.hh b/src/libfetchers/git-utils.hh index 12cee5db1..2db64e438 100644 --- a/src/libfetchers/git-utils.hh +++ b/src/libfetchers/git-utils.hh @@ -70,6 +70,8 @@ struct GitRepo virtual WorkdirInfo getWorkdirInfo() = 0; + static WorkdirInfo getCachedWorkdirInfo(const std::filesystem::path & path); + /* Get the ref that HEAD points to. */ virtual std::optional getWorkdirRef() = 0; diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index d47e731f1..a584542d1 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -431,7 +431,7 @@ struct GitInputScheme : InputScheme // If this is a local directory and no ref or revision is // given, then allow the use of an unclean working tree. if (!input.getRef() && !input.getRev() && repoInfo.isLocal) - repoInfo.workdirInfo = GitRepo::openRepo(repoInfo.url)->getWorkdirInfo(); + repoInfo.workdirInfo = GitRepo::getCachedWorkdirInfo(repoInfo.url); return repoInfo; }