1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 02:36:01 +02:00

Bug 515500: Preserve known line numbers when updating ui

This resolves a significant UI performance regression so
now line numbers don't need to be recalculated for areas
where they are already known.

Change-Id: I4668d620cde24b7cd8c6a22e9c022eaf5b237ff2
(cherry picked from commit 679896ec6e)
This commit is contained in:
Jonah Graham 2017-07-08 16:24:41 +01:00
parent e37a9e015e
commit 3c6f7a3e9e
3 changed files with 50 additions and 14 deletions

View file

@ -53,24 +53,30 @@ public class BuildConsolePartitionerEditDataTest {
assertThat(update0.getNewContents(), is(""));
assertThat(update0.getStreamsNeedingNotifcation(), is(empty()));
assertThat(update0.needsClearDocumentMarkerManager(), is(true));
assertThat(update0.getOffset(), is(0L));
data.append("Line of text\n", stream1, null);
UpdateUIData update1 = data.getUpdate();
assertThat(update1.getNewContents(), is("Line of text\n"));
assertThat(update1.getStreamsNeedingNotifcation(), is(Arrays.asList(stream1)));
assertThat(update1.needsClearDocumentMarkerManager(), is(false));
assertThat(update1.getOffset(), is(0L));
data.append("Another line of text\n", stream2, null);
UpdateUIData update2 = data.getUpdate();
assertThat(update2.getNewContents(), is("Line of text\nAnother line of text\n"));
assertThat(update2.getStreamsNeedingNotifcation(), is(Arrays.asList(stream2)));
assertThat(update2.needsClearDocumentMarkerManager(), is(false));
assertThat(update2.getOffset(), is(0L));
}
@Test
public void testOverflow() {
StringBuilder all = new StringBuilder();
for (int i = 0; i < DEFAULT_MAX_LINES * 4; i++) {
data.append("Line " + i + "\n", stream1, null);
String text = "Line " + i + "\n";
data.append(text, stream1, null);
all.append(text);
}
UpdateUIData update = data.getUpdate();
@ -86,6 +92,9 @@ public class BuildConsolePartitionerEditDataTest {
assertThat(contents, endsWith("Line " + lastLine + "\n"));
int firstLine = lastLine - newlines + 1;
assertThat(contents, startsWith("Line " + firstLine + "\n"));
long expectedOffset = all.indexOf(contents);
assertThat(update.getOffset(), is(expectedOffset));
}
@Test

View file

@ -26,6 +26,7 @@ import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
@ -104,6 +105,8 @@ public class BuildConsolePartitioner
private int fUpdateDelay = BuildConsolePreferencePage.DEFAULT_BUILDCONSOLE_UPDATE_DELAY_MS;
private long fOffset;
/**
* Construct a partitioner that is not associated with a specific project
*/
@ -251,19 +254,23 @@ public class BuildConsolePartitioner
fDocumentMarkerManager.clear();
}
/*
* This call is slow, it updates the UI as a side effect.
*
* XXX: Doing a set on the whole document means that all the line
* numbers need to be recalculated. This can be optimized further by
* keeping track of what needs to be edited. However, for now this
* optimization has not been done because although this leads to
* increased CPU usage, it does not lead to a delay in total processing
* time, but rather to a decrease in frame rate. Furthermore, if the
* document overflows, the document's line numbers need to be
* recalculated anyway, so little benefit.
*/
fDocument.set(update.getNewContents());
try {
long offsetChangeSinceLastUpdate = update.getOffset() - fOffset;
int toTrim = (int) Math.min(offsetChangeSinceLastUpdate, fDocument.getLength());
int length = fDocument.getLength();
String newContents = update.getNewContents();
String appendContents = newContents.substring(length - toTrim);
// The append has to be done before the delete from head
// to avoid document becoming 0 length and therefore the
// listeners assume the document has been cleared
fDocument.replace(length + toTrim, 0, appendContents);
fDocument.replace(0, toTrim, ""); //$NON-NLS-1$
} catch (BadLocationException e) {
fDocument.set(update.getNewContents());
}
fOffset = update.getOffset();
}
/**

View file

@ -36,6 +36,11 @@ public class BuildConsolePartitionerEditData {
*/
boolean needsClearDocumentMarkerManager();
/**
* The content's offset since beginning of time.
*/
long getOffset();
/**
* New contents for the build console.
*/
@ -70,6 +75,11 @@ public class BuildConsolePartitionerEditData {
*/
private boolean fClearDocumentMarkerManager = false;
/**
* Offset of the start of the document since the beginning of time.
*/
private long fOffset = 0;
/**
* Editable document, all modifications are made to this copy of the
* document, then the UI thread occasionally gets these updates
@ -86,6 +96,7 @@ public class BuildConsolePartitionerEditData {
*/
private Set<IBuildConsoleStreamDecorator> fEditStreams = new HashSet<>();
public BuildConsolePartitionerEditData(int maxLines) {
fMaxLines = maxLines;
}
@ -105,6 +116,7 @@ public class BuildConsolePartitionerEditData {
synchronized (this) {
fEditPartitions.clear();
fClearDocumentMarkerManager = true;
fOffset += fEditStringBuilder.length();
fEditStringBuilder.setLength(0);
fEditLineCount = 0;
}
@ -239,6 +251,7 @@ public class BuildConsolePartitionerEditData {
fEditPartitions = newParitions;
fClearDocumentMarkerManager = true;
fOffset += offsetToOffset;
fEditStringBuilder.delete(0, offsetToOffset);
fEditLineCount = newNewlineCount;
@ -287,11 +300,13 @@ public class BuildConsolePartitionerEditData {
*/
public UpdateUIData getUpdate() {
boolean clearDocumentMarkerManager;
long newOffset;
String newConents;
List<ITypedRegion> newPartitions;
List<IBuildConsoleStreamDecorator> streamsNeedingNotifcation;
synchronized (this) {
newOffset = fOffset;
newConents = fEditStringBuilder.toString();
newPartitions = new ArrayList<>(fEditPartitions);
clearDocumentMarkerManager = fClearDocumentMarkerManager;
@ -321,6 +336,11 @@ public class BuildConsolePartitionerEditData {
public String getNewContents() {
return newConents;
}
@Override
public long getOffset() {
return newOffset;
}
};
}