summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaushik Lingarkar <kaushik.lingarkar@linaro.org>2022-10-26 10:00:39 -0700
committerKaushik Lingarkar <kaushik.lingarkar@linaro.org>2022-10-28 19:11:47 +0000
commitb5e7cedd00abd8e48ec670bbe845b4f009912974 (patch)
tree4d08447b23f73b96bb2a9b921c8faafd923135ae
parenteb9031212cda1f960dbdfa76c913bba6d19c035d (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.java21
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);
}