Improve performance of ReceiveCommits for repos with many refs

Commit 2fbea6c already improved performance of ReceiveCommits for repos
which have a lot of refs (>100000). In this case adding all existing
refs to RevWalk's as "uninteresting" caused performance problems. But
there was another place in ReceiveCommands where we added all existing
refs as uninteresting: in validateNewCommits(). This commit improves
the performance of this method in the same way as it was done in
2fbea6c.

Change-Id: I1ce6e4198daeabbcf5b8da61e6209b45672eb4be
This commit is contained in:
Christian Halstrick
2012-12-21 08:48:37 +01:00
committed by Shawn Pearce
parent cc446ff460
commit 9bcd4750fc

View File

@@ -249,7 +249,6 @@ public class ReceiveCommits {
private final Map<RevCommit, ReplaceRequest> replaceByCommit =
new HashMap<RevCommit, ReplaceRequest>();
private Collection<ObjectId> existingObjects;
private Map<ObjectId, Ref> refsById;
private String destTopicName;
@@ -1116,22 +1115,7 @@ public class ReceiveCommits {
try {
Set<ObjectId> existing = Sets.newHashSet();
walk.markStart(walk.parseCommit(newChange.getNewId()));
for (Ref ref : repo.getAllRefs().values()) {
if (ref.getObjectId() == null) {
continue;
} else if (ref.getName().startsWith("refs/changes/")) {
existing.add(ref.getObjectId());
} else if (ref.getName().startsWith(R_HEADS)
|| ref.getName().equals(destBranchCtl.getRefName())) {
try {
walk.markUninteresting(walk.parseCommit(ref.getObjectId()));
} catch (IOException e) {
log.warn(String.format("Invalid ref %s in %s",
ref.getName(), project.getName()), e);
continue;
}
}
}
markHeadsAsUninteresting(walk, existing);
List<ChangeLookup> pending = Lists.newArrayList();
final Set<Change.Key> newChangeIds = new HashSet<Change.Key>();
@@ -1229,6 +1213,26 @@ public class ReceiveCommits {
return newChanges;
}
private void markHeadsAsUninteresting(final RevWalk walk, Set<ObjectId> existing) {
for (Ref ref : repo.getAllRefs().values()) {
if (ref.getObjectId() == null) {
continue;
} else if (ref.getName().startsWith("refs/changes/")) {
existing.add(ref.getObjectId());
} else if (ref.getName().startsWith(R_HEADS)
|| (destBranchCtl != null && ref.getName().equals(destBranchCtl.getRefName()))) {
try {
walk.markUninteresting(walk.parseCommit(ref.getObjectId()));
} catch (IOException e) {
log.warn(String.format("Invalid ref %s in %s",
ref.getName(), project.getName()), e);
continue;
}
}
}
}
private static boolean isValidChangeId(String idStr) {
return idStr.matches("^I[0-9a-fA-F]{40}$") && !idStr.matches("^I00*$");
}
@@ -1811,18 +1815,15 @@ public class ReceiveCommits {
walk.reset();
walk.sort(RevSort.NONE);
try {
Set<ObjectId> existing = Sets.newHashSet();
walk.markStart(walk.parseCommit(cmd.getNewId()));
for (ObjectId id : existingObjects()) {
try {
walk.markUninteresting(walk.parseCommit(id));
} catch (IOException e) {
continue;
}
}
markHeadsAsUninteresting(walk, existing);
RevCommit c;
while ((c = walk.next()) != null) {
if (!validCommit(ctl, cmd, c)) {
if (existing.contains(c)) {
continue;
} else if (!validCommit(ctl, cmd, c)) {
break;
}
}
@@ -1832,17 +1833,6 @@ public class ReceiveCommits {
}
}
private Collection<ObjectId> existingObjects() {
if (existingObjects == null) {
Map<String, Ref> refs = repo.getAllRefs();
existingObjects = new ArrayList<ObjectId>(refs.size());
for (Ref r : refs.values()) {
existingObjects.add(r.getObjectId());
}
}
return existingObjects;
}
private boolean validCommit(final RefControl ctl, final ReceiveCommand cmd,
final RevCommit c) throws MissingObjectException, IOException {
rp.getRevWalk().parseBody(c);