Split intraline differences into their own cache
The bulk of the running time for loading a PatchList entry from the PatchListCache is actually within the intraline difference code. Assuming no bugs, running JGit's DiffFormatter and converting the results is typically sub-second, even for a very large change that has renames. By deferring the intraline difference logic until its actually required to display a particular file allows file lists to load very quickly, and doesn't penalize users who have disabled the intraline difference setting in their account preferences. This also offers a work around for the dreaded "patch of death" situation. When a bad file is encountered and it won't load, users can temporarily switch off intraline difference and open the file anyway. Unfortunately the server will still have at least one worker thread stuck generating the intraline difference cache record, but at least the change is still viewable. Change-Id: I61bbd3d068bd9b3da9d1018c0f66969a5b6ff58e Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -29,7 +29,6 @@ import com.google.gerrit.reviewdb.Patch.ChangeType;
|
||||
import com.google.gerrit.reviewdb.Patch.PatchType;
|
||||
|
||||
import org.eclipse.jgit.diff.Edit;
|
||||
import org.eclipse.jgit.diff.ReplaceEdit;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.patch.CombinedFileHeader;
|
||||
@@ -183,27 +182,13 @@ public class PatchListEntry {
|
||||
|
||||
writeVarInt32(out, edits.size());
|
||||
for (final Edit e : edits) {
|
||||
write(out, e);
|
||||
|
||||
if (e instanceof ReplaceEdit) {
|
||||
ReplaceEdit r = (ReplaceEdit) e;
|
||||
writeVarInt32(out, r.getInternalEdits().size());
|
||||
for (Edit i : r.getInternalEdits()) {
|
||||
write(out, i);
|
||||
}
|
||||
} else {
|
||||
writeVarInt32(out, 0);
|
||||
}
|
||||
writeVarInt32(out, e.getBeginA());
|
||||
writeVarInt32(out, e.getEndA());
|
||||
writeVarInt32(out, e.getBeginB());
|
||||
writeVarInt32(out, e.getEndB());
|
||||
}
|
||||
}
|
||||
|
||||
private void write(final OutputStream out, final Edit e) throws IOException {
|
||||
writeVarInt32(out, e.getBeginA());
|
||||
writeVarInt32(out, e.getEndA());
|
||||
writeVarInt32(out, e.getBeginB());
|
||||
writeVarInt32(out, e.getEndB());
|
||||
}
|
||||
|
||||
static PatchListEntry readFrom(final InputStream in) throws IOException {
|
||||
final ChangeType changeType = readEnum(in, ChangeType.values());
|
||||
final PatchType patchType = readEnum(in, PatchType.values());
|
||||
@@ -216,16 +201,11 @@ public class PatchListEntry {
|
||||
final int editCount = readVarInt32(in);
|
||||
final Edit[] editArray = new Edit[editCount];
|
||||
for (int i = 0; i < editCount; i++) {
|
||||
editArray[i] = readEdit(in);
|
||||
|
||||
int innerCount = readVarInt32(in);
|
||||
if (0 < innerCount) {
|
||||
Edit[] inner = new Edit[innerCount];
|
||||
for (int innerIdx = 0; innerIdx < innerCount; innerIdx++) {
|
||||
inner[innerIdx] = readEdit(in);
|
||||
}
|
||||
editArray[i] = new ReplaceEdit(editArray[i], toList(inner));
|
||||
}
|
||||
int beginA = readVarInt32(in);
|
||||
int endA = readVarInt32(in);
|
||||
int beginB = readVarInt32(in);
|
||||
int endB = readVarInt32(in);
|
||||
editArray[i] = new Edit(beginA, endA, beginB, endB);
|
||||
}
|
||||
|
||||
return new PatchListEntry(changeType, patchType, oldName, newName, hdr,
|
||||
@@ -236,14 +216,6 @@ public class PatchListEntry {
|
||||
return Collections.unmodifiableList(Arrays.asList(l));
|
||||
}
|
||||
|
||||
private static Edit readEdit(final InputStream in) throws IOException {
|
||||
final int beginA = readVarInt32(in);
|
||||
final int endA = readVarInt32(in);
|
||||
final int beginB = readVarInt32(in);
|
||||
final int endB = readVarInt32(in);
|
||||
return new Edit(beginA, endA, beginB, endB);
|
||||
}
|
||||
|
||||
private static byte[] compact(final FileHeader h) {
|
||||
final int end = end(h);
|
||||
if (h.getStartOffset() == 0 && end == h.getBuffer().length) {
|
||||
|
||||
Reference in New Issue
Block a user