ChangeIsVisibleToPredicate: Only create PermissionBackend.WithUser once
No need to repeat this work for every change we're trying to match and
unless the `user` is the current user, we'll be creating a
new IdentifiedUser each time which adds an overhead that degrades
query performance.
On a site with around 20k open changes a query where the visibility is
checked for an account that cannot see most/all changes improves from
~14s to ~9s.
Change-Id: I9e797fcb3622ed1b0d8313d843c95f7dfaf490f5
Release-Notes: Improve performance of queries that check the visibility of changes wrt a non-current user
diff --git a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
index a66c43ae..bb10de5 100644
--- a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
+++ b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
@@ -44,9 +44,8 @@
protected final ChangeNotes.Factory notesFactory;
protected final CurrentUser user;
- protected final PermissionBackend permissionBackend;
protected final ProjectCache projectCache;
- private final Provider<AnonymousUser> anonymousUserProvider;
+ private final PermissionBackend.WithUser withUser;
@Inject
public ChangeIsVisibleToPredicate(
@@ -58,9 +57,14 @@
super(ChangeQueryBuilder.FIELD_VISIBLETO, IndexUtils.describe(user));
this.notesFactory = notesFactory;
this.user = user;
- this.permissionBackend = permissionBackend;
this.projectCache = projectCache;
- this.anonymousUserProvider = anonymousUserProvider;
+ withUser =
+ user.isIdentifiedUser()
+ ? permissionBackend.absentUser(user.getAccountId())
+ : permissionBackend.user(
+ Optional.of(user)
+ .filter(u -> u instanceof GroupBackedUser || u instanceof InternalUser)
+ .orElseGet(anonymousUserProvider::get));
}
@Override
@@ -79,17 +83,10 @@
return false;
}
if (!projectState.get().statePermitsRead()) {
- logger.atFine().log("Filter out change %s of non-reabable project %s", cd, cd.project());
+ logger.atFine().log("Filter out change %s of non-readable project %s", cd, cd.project());
return false;
}
- PermissionBackend.WithUser withUser =
- user.isIdentifiedUser()
- ? permissionBackend.absentUser(user.getAccountId())
- : permissionBackend.user(
- Optional.of(user)
- .filter(u -> u instanceof GroupBackedUser || u instanceof InternalUser)
- .orElseGet(anonymousUserProvider::get));
try {
withUser.change(cd).check(ChangePermission.READ);
} catch (PermissionBackendException e) {