From 4d44cf806ddfa8d051f2d6b1289fa3b67b0daf2e Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Fri, 21 Oct 2011 17:00:07 -0400 Subject: [PATCH] Cache repository sizes and default metrics for performance boost --- src/com/gitblit/GitBlit.java | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 50eeb9e..51d5612 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -60,12 +60,15 @@ import com.gitblit.models.FederationModel; import com.gitblit.models.FederationProposal; import com.gitblit.models.FederationSet; +import com.gitblit.models.Metric; +import com.gitblit.models.ObjectCache; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.ByteFormat; import com.gitblit.utils.FederationUtils; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.JsonUtils; +import com.gitblit.utils.MetricUtils; import com.gitblit.utils.StringUtils; /** @@ -96,6 +99,10 @@ .synchronizedList(new ArrayList<FederationModel>()); private final Map<String, FederationModel> federationPullResults = new ConcurrentHashMap<String, FederationModel>(); + + private final ObjectCache<Long> repositorySizeCache = new ObjectCache<Long>(); + + private final ObjectCache<List<Metric>> repositoryMetricsCache = new ObjectCache<List<Metric>>(); private RepositoryResolver<Void> repositoryResolver; @@ -419,6 +426,16 @@ } /** + * Clears all the cached data for the specified repository. + * + * @param repositoryName + */ + public void clearRepositoryCache(String repositoryName) { + repositorySizeCache.remove(repositoryName); + repositoryMetricsCache.remove(repositoryName); + } + + /** * Returns the list of all repositories available to Gitblit. This method * does not consider user access permissions. * @@ -550,14 +567,22 @@ } /** - * Returns the size in bytes of the repository. + * Returns the size in bytes of the repository. Gitblit caches the + * repository sizes to reduce the performance penalty of recursive + * calculation. The cache is updated if the repository has been changed + * since the last calculation. * * @param model * @return size in bytes */ public long calculateSize(RepositoryModel model) { + if (repositorySizeCache.hasCurrent(model.name, model.lastChange)) { + return repositorySizeCache.getObject(model.name); + } File gitDir = FileKey.resolve(new File(repositoriesFolder, model.name), FS.DETECTED); - return com.gitblit.utils.FileUtils.folderSize(gitDir); + long size = com.gitblit.utils.FileUtils.folderSize(gitDir); + repositorySizeCache.updateObject(model.name, model.lastChange, size); + return size; } /** @@ -596,7 +621,26 @@ } /** - * Returns the gitblit string vlaue for the specified key. If key is not + * Returns the metrics for the default branch of the specified repository. + * This method builds a metrics cache. The cache is updated if the + * repository is updated. A new copy of the metrics list is returned on each + * call so that modifications to the list are non-destructive. + * + * @param model + * @param repository + * @return a new array list of metrics + */ + public List<Metric> getRepositoryDefaultMetrics(RepositoryModel model, Repository repository) { + if (repositoryMetricsCache.hasCurrent(model.name, model.lastChange)) { + return new ArrayList<Metric>(repositoryMetricsCache.getObject(model.name)); + } + List<Metric> metrics = MetricUtils.getDateMetrics(repository, null, true, null); + repositoryMetricsCache.updateObject(model.name, model.lastChange, metrics); + return new ArrayList<Metric>(metrics); + } + + /** + * Returns the gitblit string value for the specified key. If key is not * set, returns defaultValue. * * @param config @@ -678,6 +722,9 @@ "Failed to rename repository permissions ''{0}'' to ''{1}''.", repositoryName, repository.name)); } + + // clear the cache + clearRepositoryCache(repositoryName); } // load repository @@ -758,6 +805,9 @@ return true; } } + + // clear the repository cache + clearRepositoryCache(repositoryName); } catch (Throwable t) { logger.error(MessageFormat.format("Failed to delete repository {0}", repositoryName), t); } -- Gitblit v1.9.1