From a4a53664446b5f6a466b386773d89ff992093617 Mon Sep 17 00:00:00 2001 From: Gustaf Lundh Date: Tue, 19 Nov 2013 17:21:28 +0100 Subject: [PATCH] Performance Fix: Minimize number of advertisedHaves While we set up hooks in ReceiveCommits to minimize the number of advertised refs (for instance filtering out refs/changes and refs/cache-automerge refs), their objectIds will still be added to BaseReceivePack.advertisedHaves (JGit), leading to an unnecessarily complex commit graph for JGit to traverse when checking for commit connectivity in BaseReceivePack.checkConnectivity(). By filtering the refs before the objectIds are added to advertisedHaves, lots of time can be saved when pushing to complex Gits. Push times for one of our Gits (warm caches): Before fix: real 0m42.926s After fix: real 0m6.325s This Git has around 90k change/ps refs. Change-Id: I2f0a0830bd733f908f0aeaf1eaf0412dae428a16 --- .../google/gerrit/server/git/ReceiveCommits.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java index bcc30144fc..897b53a81c 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java @@ -18,7 +18,6 @@ import static com.google.gerrit.reviewdb.client.Change.INITIAL_PATCH_SET_ID; import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN; import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromApprovals; import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters; - import static org.eclipse.jgit.lib.Constants.R_HEADS; import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED; import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK; @@ -114,6 +113,7 @@ import org.eclipse.jgit.transport.AdvertiseRefsHook; import org.eclipse.jgit.transport.AdvertiseRefsHookChain; import org.eclipse.jgit.transport.BaseReceivePack; import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.transport.RefFilter; import org.eclipse.jgit.transport.ReceiveCommand.Result; import org.eclipse.jgit.transport.ReceivePack; import org.eclipse.jgit.transport.UploadPack; @@ -363,6 +363,20 @@ public class ReceiveCommits { rp.setAllowDeletes(true); rp.setAllowNonFastForwards(true); rp.setCheckReceivedObjects(true); + rp.setRefFilter(new RefFilter() { + @Override + public Map filter(Map refs) { + Map filteredRefs = Maps.newHashMapWithExpectedSize(refs.size()); + for (Map.Entry e : refs.entrySet()) { + String name = e.getKey(); + if (!name.startsWith("refs/changes/") + && !name.startsWith(GitRepositoryManager.REFS_CACHE_AUTOMERGE)) { + filteredRefs.put(name, e.getValue()); + } + } + return filteredRefs; + } + }); if (!projectControl.allRefsAreVisible()) { rp.setCheckReferencedObjectsAreReachable(config.checkReferencedObjectsAreReachable);