diff options
author | Kaushik Lingarkar <kaushik.lingarkar@linaro.org> | 2022-10-26 10:00:39 -0700 |
---|---|---|
committer | Kaushik Lingarkar <kaushik.lingarkar@linaro.org> | 2022-10-28 19:11:47 +0000 |
commit | b5e7cedd00abd8e48ec670bbe845b4f009912974 (patch) | |
tree | 4d08447b23f73b96bb2a9b921c8faafd923135ae | |
parent | eb9031212cda1f960dbdfa76c913bba6d19c035d (diff) |
Cache repository locations in LocalDiskRepositoryManager
Obtaining the actual location of a repository using base-path
and project name can be slow as it involves some guessing to
locate the repository. Cache the locations once they are
obtained to avoid repeated work, thereby improving performance
when opening repositories.
For example, on a site with 20k repositories on NFS, ls-projects
with this change takes ~60s and ~90s without. Also, a query which
wraps a large (~2k) list of manifest[1] operators will take ~300ms
with this change and ~2s without it.
[1] https://gerrit.googlesource.com/plugins/manifest
Release-Notes: skip
Change-Id: I8eab3c813c4ac9433e93c7ace96d38efe332be27
-rw-r--r-- | java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java b/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java index 1fdf194016..2c0fdca83f 100644 --- a/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java +++ b/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java @@ -33,8 +33,10 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; import java.util.EnumSet; +import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ConfigConstants; @@ -108,6 +110,7 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager { } private final Path basePath; + private final Map<Project.NameKey, FileKey> fileKeyByProject = new ConcurrentHashMap<>(); @Inject LocalDiskRepositoryManager(SitePaths site, @GerritServerConfig Config cfg) { @@ -129,17 +132,23 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager { @Override public Repository openRepository(Project.NameKey name) throws RepositoryNotFoundException { - return openRepository(getBasePath(name), name); - } + FileKey cachedLocation = fileKeyByProject.get(name); + if (cachedLocation != null) { + try { + return RepositoryCache.open(cachedLocation); + } catch (IOException e) { + fileKeyByProject.remove(name, cachedLocation); + } + } - private Repository openRepository(Path path, Project.NameKey name) - throws RepositoryNotFoundException { if (isUnreasonableName(name)) { throw new RepositoryNotFoundException("Invalid name: " + name); } - FileKey loc = FileKey.lenient(path.resolve(name.get()).toFile(), FS.DETECTED); + FileKey location = FileKey.lenient(getBasePath(name).resolve(name.get()).toFile(), FS.DETECTED); try { - return RepositoryCache.open(loc); + Repository repo = RepositoryCache.open(location); + fileKeyByProject.put(name, location); + return repo; } catch (IOException e) { throw new RepositoryNotFoundException("Cannot open repository " + name, e); } |