summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Milanesio <luca.milanesio@gmail.com>2022-05-29 21:56:14 +0100
committerLuca Milanesio <luca.milanesio@gmail.com>2022-05-30 22:49:54 -0700
commit4757ad473f87f953edfd1d6d6590839d395ab390 (patch)
tree2a1b5390a6d0a26e054ab51f95eef9e0a617224d
parent5003460963903cfe6294f27b5836ad4df657ea94 (diff)
Lazy load change notes when submit by push
Lazy load the change notes associated with the change to merge when one or more changes are submitted by a git push of the change onto its target branch. When a single change is merged through git push, we need to find which one is the corresponding change meta to be checked and merged. However, the building of the entire set of open changes against the target branch, indexed by their change key was having the side-effect of loading eagerly changes notes from their /meta ref. Loading all changes notes can be very slow, O(mins), on repositories with a large number of refs on slow storage and, also, it is completely unneeded in this use case. Loading all the change notes for all open changes had increased the time to submit a change from a few seconds (via the GUI) to a few minutes (via git push). Release-Notes: Performance improvement of change submit via push Change-Id: I646bc7b13f3359816b6be6354e15ddb5412bfa38
-rw-r--r--java/com/google/gerrit/server/git/receive/ReceiveCommits.java22
1 files changed, 13 insertions, 9 deletions
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 77f1e1ec5e..945eedc9f0 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -3105,7 +3105,7 @@ class ReceiveCommits {
}
ListMultimap<ObjectId, Ref> byCommit = changeRefsById();
- Map<Change.Key, ChangeNotes> byKey = null;
+ Map<Change.Key, ChangeData> changeDataByKey = null;
List<ReplaceRequest> replaceAndClose = new ArrayList<>();
int existingPatchSets = 0;
@@ -3128,17 +3128,18 @@ class ReceiveCommits {
}
for (String changeId : c.getFooterLines(CHANGE_ID)) {
- if (byKey == null) {
- byKey = executeIndexQuery(() -> openChangesByKeyByBranch(branch));
+ if (changeDataByKey == null) {
+ changeDataByKey = executeIndexQuery(() -> openChangesByKeyByBranch(branch));
}
- ChangeNotes onto = byKey.get(new Change.Key(changeId.trim()));
+ ChangeData onto = changeDataByKey.get(new Change.Key(changeId.trim()));
if (onto != null) {
newPatchSets++;
// Hold onto this until we're done with the walk, as the call to
// req.validate below calls isMergedInto which resets the walk.
- ReplaceRequest req = new ReplaceRequest(onto.getChangeId(), c, cmd, false);
- req.notes = onto;
+ ChangeNotes ontoNotes = onto.notes();
+ ReplaceRequest req = new ReplaceRequest(ontoNotes.getChangeId(), c, cmd, false);
+ req.notes = ontoNotes;
replaceAndClose.add(req);
continue COMMIT;
}
@@ -3207,12 +3208,15 @@ class ReceiveCommits {
}
}
- private Map<Change.Key, ChangeNotes> openChangesByKeyByBranch(Branch.NameKey branch)
+ private Map<Change.Key, ChangeData> openChangesByKeyByBranch(Branch.NameKey branch)
throws OrmException {
- Map<Change.Key, ChangeNotes> r = new HashMap<>();
+ Map<Change.Key, ChangeData> r = new HashMap<>();
for (ChangeData cd : queryProvider.get().byBranchOpen(branch)) {
try {
- r.put(cd.change().getKey(), cd.notes());
+ // ChangeData is not materialised into a ChangeNotes for avoiding
+ // to load a potentially large number of changes meta-data into memory
+ // which would cause unnecessary disk I/O, CPU and heap utilisation.
+ r.put(cd.change().getKey(), cd);
} catch (NoSuchChangeException e) {
// Ignore deleted change
}