Cache parsed ChangeNotes
By instrumenting a dev server, I found that loading the change screen for a single change plus 2 related changes and 2 conflicting changes results in a whopping 25 loads of a ChangeNotes. On a SQL database that's not too terrible, but git storage is enough slower and more memory-intensive than SQL that this is noticeable. Plus, the ChangeNotes approach is to parse EVERYTHING, which is often more than we need. Solve this problem in the way we solve all problems: throw a cache in front of it. This data has the nice property that the entities parsed from a particular SHA-1 are immutable forever, so we don't need to worry about invalidation like we would with a cache keyed by, say, change number. Change-Id: I4bbb9bf82f8f228b3ae8333a288af35d163c050f
This commit is contained in:
@@ -22,8 +22,10 @@ import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
|
||||
import static com.google.gerrit.testutil.TestChanges.incrementPatchSet;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
@@ -52,6 +54,7 @@ import com.google.gerrit.testutil.TestChanges;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
@@ -802,9 +805,15 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
|
||||
RevCommit commit = tr.commit().message("PS1 again").create();
|
||||
update.setCommit(rw, commit);
|
||||
update.commit();
|
||||
exception.expect(OrmException.class);
|
||||
exception.expectMessage("Multiple revisions parsed for patch set");
|
||||
notes = newNotes(c);
|
||||
|
||||
try {
|
||||
notes = newNotes(c);
|
||||
fail("Expected IOException");
|
||||
} catch (OrmException e) {
|
||||
assertCause(e, ConfigInvalidException.class,
|
||||
"Multiple revisions parsed for patch set 1:"
|
||||
+ " RevId{" + commit.name() + "} and " + ps.getRevision().get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2285,4 +2294,20 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
|
||||
return ref != null ? ref.getObjectId() : null;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCause(Throwable e,
|
||||
Class<? extends Throwable> expectedClass, String expectedMsg) {
|
||||
Throwable cause = null;
|
||||
for (Throwable t : Throwables.getCausalChain(e)) {
|
||||
if (expectedClass.isAssignableFrom(t.getClass())) {
|
||||
cause = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertThat(cause)
|
||||
.named(expectedClass.getSimpleName() + " in causal chain of:\n"
|
||||
+ Throwables.getStackTraceAsString(e))
|
||||
.isNotNull();
|
||||
assertThat(cause.getMessage()).isEqualTo(expectedMsg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user