SideBySide2: Batch adjustments of padding widgets
Right after the view opens a number of deferred tasks fire, one for each padding region and comment widget to rescale the padding size. Every time these update a CM3 controlled property the CM3 instance has to reflow its DOM, which is relatively expensive in the browser. Batch the deferred work inside of the SideBySide2 instance as a list of Runnables. If any tasks are scheduled, schedule only one deferred task to run all batched items inside of an operation() wrapper. This allows CM3 to batch up the updates and reflow its DOM only once per side, rather than once per padding widget. In one example file (some version of ChangeScreen2.java) with a handful of diff chunks and test comments this batching process saves 40.9 ms during the initial display of the file. The exact amount of time saved depends on the complexity of the file, the delta chunks and the number of comments, but this was a fairly typical trivial example. Real world files may see an even larger savings. Change-Id: Ib84c67d2f999fb7df5731ca3389a79b53da45a01
This commit is contained in:
committed by
Michael Zhou
parent
5c8a75b4b5
commit
c962cc0bd6
@@ -17,8 +17,6 @@ package com.google.gerrit.client.diff;
|
||||
import com.google.gerrit.client.changes.CommentInfo;
|
||||
import com.google.gerrit.client.diff.PaddingManager.PaddingWidgetWrapper;
|
||||
import com.google.gerrit.client.diff.SidePanel.GutterWrapper;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.event.dom.client.MouseOutEvent;
|
||||
import com.google.gwt.event.dom.client.MouseOutHandler;
|
||||
import com.google.gwt.event.dom.client.MouseOverEvent;
|
||||
@@ -82,9 +80,9 @@ abstract class CommentBox extends Composite {
|
||||
if (!getCommentInfo().has_line()) {
|
||||
return;
|
||||
}
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
parent.defer(new Runnable() {
|
||||
@Override
|
||||
public void execute() {
|
||||
public void run() {
|
||||
assert selfWidgetWrapper != null;
|
||||
selfWidgetWrapper.getWidget().changed();
|
||||
if (diffChunkInfo != null) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
@@ -236,12 +235,7 @@ class DraftBox extends CommentBox {
|
||||
getCm().focus();
|
||||
getSelfWidgetWrapper().getWidget().clear();
|
||||
getGutterWrapper().remove();
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
resizePaddingWidget();
|
||||
}
|
||||
});
|
||||
resizePaddingWidget();
|
||||
}
|
||||
|
||||
@UiHandler("message")
|
||||
|
||||
@@ -134,6 +134,7 @@ public class SideBySide2 extends Screen {
|
||||
private KeyCommandSet keysComment;
|
||||
private KeyCommandSet keysOpenByEnter;
|
||||
private List<HandlerRegistration> handlers;
|
||||
private List<Runnable> deferred;
|
||||
|
||||
public SideBySide2(
|
||||
PatchSet.Id base,
|
||||
@@ -605,6 +606,7 @@ public class SideBySide2 extends Screen {
|
||||
}
|
||||
|
||||
CommentBox addCommentBox(CommentInfo info, CommentBox box) {
|
||||
box.setParent(this);
|
||||
diffTable.add(box);
|
||||
DisplaySide side = box.getSide();
|
||||
CodeMirror cm = getCmFromSide(side);
|
||||
@@ -643,7 +645,6 @@ public class SideBySide2 extends Screen {
|
||||
LineWidget boxWidget = addLineWidget(cm, line, box, config);
|
||||
box.setPaddingManager(manager);
|
||||
box.setSelfWidgetWrapper(new PaddingWidgetWrapper(boxWidget, box.getElement()));
|
||||
box.setParent(this);
|
||||
if (otherChunk == null) {
|
||||
box.setDiffChunkInfo(myChunk);
|
||||
}
|
||||
@@ -966,9 +967,9 @@ public class SideBySide2 extends Screen {
|
||||
* key (or j/k) is held down. Performance on Chrome is fine
|
||||
* without the deferral.
|
||||
*/
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
defer(new Runnable() {
|
||||
@Override
|
||||
public void execute() {
|
||||
public void run() {
|
||||
LineHandle handle = cm.getLineHandleVisualStart(
|
||||
cm.getCursor("end").getLine());
|
||||
if (cm.hasActiveLine() && cm.getActiveLine().equals(handle)) {
|
||||
@@ -1203,6 +1204,33 @@ public class SideBySide2 extends Screen {
|
||||
return (index + diffChunks.size()) % diffChunks.size();
|
||||
}
|
||||
|
||||
void defer(Runnable thunk) {
|
||||
if (deferred == null) {
|
||||
final ArrayList<Runnable> list = new ArrayList<Runnable>();
|
||||
deferred = list;
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
deferred = null;
|
||||
cmA.operation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cmB.operation(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Runnable thunk : list) {
|
||||
thunk.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
deferred.add(thunk);
|
||||
}
|
||||
|
||||
void resizePaddingOnOtherSide(DisplaySide mySide, int line) {
|
||||
CodeMirror cm = getCmFromSide(mySide);
|
||||
LineHandle handle = cm.getLineHandle(line);
|
||||
@@ -1258,9 +1286,9 @@ public class SideBySide2 extends Screen {
|
||||
lineActiveBoxMap.get(handle).resizePaddingWidget();
|
||||
}
|
||||
if (linePaddingOnOtherSideMap.containsKey(handle)) {
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
defer(new Runnable() {
|
||||
@Override
|
||||
public void execute() {
|
||||
public void run() {
|
||||
resizePaddingOnOtherSide(side, instance.getLineNumber(handle));
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user