Fixes issue 3148 by improving the performance of FlowPanel.clear() by a hundred to one on IE.
Review by:jlabanca
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4468 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClear.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClear.java
new file mode 100644
index 0000000..558aeed
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClear.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.ControlInputPanel;
+import com.google.gwt.museum.client.common.SimpleLogger;
+import com.google.gwt.museum.client.common.ControlInputPanel.IntegerInput;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * Originally, on IE, about three seconds to distroy
+ */
+/**
+ * Tests bad behavior for clear.
+ *
+ * <pre>
+ * ff -- 1000 flow panels, aprox 500 millis
+ * ie -- 1000 flow panels, aprox 3000 millis
+ *
+ * in new version
+ * ie -- 1000 flow panels, aprox 30-80 millis
+ * ff -- 1000 flow panels, aprox 13-50 millis
+ * </pre>
+ * <p>
+ * <img class='gallery' src='FlowPanel.png'/>
+ * </p>
+ */
+public class SpeedForClear extends AbstractIssue {
+ private Panel target;
+ private List<Widget> children = new ArrayList<Widget>();
+ private SimpleLogger log = new SimpleLogger();
+
+ @Override
+ public Widget createIssue() {
+ VerticalPanel v = new VerticalPanel();
+ ControlInputPanel p = new ControlInputPanel();
+ v.add(p);
+ v.add(log);
+ final IntegerInput size = new IntegerInput("flowpanel", 10, p);
+ Button create = new Button("create widget", new ClickHandler() {
+
+ public void onClick(ClickEvent event) {
+ createLargeFlowPanel(size.getValue());
+ }
+ });
+
+ Button distroy = new Button("time the removal", new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ Duration d = new Duration();
+ target.clear();
+
+ log.report("Took " + d.elapsedMillis() + " milliseconds to clear "
+ + size.getValue() + " widgets from a flow panel");
+ for (Widget child : children) {
+ if (child.getElement().getPropertyString("__listener") != null) {
+ throw new IllegalStateException(
+ "each child should no longer have a listener");
+ }
+ }
+ }
+ });
+ v.add(create);
+ v.add(distroy);
+ return v;
+ }
+
+ @Override
+ public String getInstructions() {
+ return "check the speed of clear methods";
+ }
+
+ @Override
+ public String getSummary() {
+ return "clear() speed check";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+
+ private void createLargeFlowPanel(int size) {
+
+ if (target != null) {
+ target.removeFromParent();
+ }
+ target = new FlowPanel();
+
+ for (int i = 0; i < size; i++) {
+ Widget w = new Label("widget-" + i);
+ target.add(w);
+ children.add(w);
+ }
+
+ RootPanel.get().add(target);
+ for (Widget child : target) {
+ if (child.getElement().getPropertyString("__listener") == null) {
+ throw new IllegalStateException("each child should now have a listener");
+ }
+ }
+ }
+
+}
diff --git a/user/src/com/google/gwt/user/client/ui/ComplexPanel.java b/user/src/com/google/gwt/user/client/ui/ComplexPanel.java
index aa26def..b7b1d52 100644
--- a/user/src/com/google/gwt/user/client/ui/ComplexPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/ComplexPanel.java
@@ -111,8 +111,8 @@
}
/**
- * Checks that <code>index</code> is in the range [0, getWidgetCount()),
- * which is the valid range on accessible indexes.
+ * Checks that <code>index</code> is in the range [0, getWidgetCount()), which
+ * is the valid range on accessible indexes.
*
* @param index the index being accessed
*/
@@ -123,8 +123,8 @@
}
/**
- * Checks that <code>index</code> is in the range [0, getWidgetCount()],
- * which is the valid range for indexes on an insertion.
+ * Checks that <code>index</code> is in the range [0, getWidgetCount()], which
+ * is the valid range for indexes on an insertion.
*
* @param index the index where insertion will occur
*/
@@ -197,4 +197,12 @@
// Adopt.
adopt(child);
}
+
+ void doLogicalClear() {
+ int size = children.size();
+ for (int i = 0; i < size; i++) {
+ orphan(children.get(i));
+ }
+ children = new WidgetCollection(this);
+ }
}
diff --git a/user/src/com/google/gwt/user/client/ui/FlowPanel.java b/user/src/com/google/gwt/user/client/ui/FlowPanel.java
index 601bac7..44f2153 100644
--- a/user/src/com/google/gwt/user/client/ui/FlowPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/FlowPanel.java
@@ -44,6 +44,12 @@
add(w, getElement());
}
+ @Override
+ public void clear() {
+ super.doLogicalClear();
+ this.getElement().setInnerHTML("");
+ }
+
/**
* Inserts a widget before the specified index.
*
diff --git a/user/test/com/google/gwt/user/client/ui/FlowPanelTest.java b/user/test/com/google/gwt/user/client/ui/FlowPanelTest.java
index d1c8b34..441ac03 100644
--- a/user/test/com/google/gwt/user/client/ui/FlowPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/FlowPanelTest.java
@@ -17,6 +17,9 @@
import com.google.gwt.junit.client.GWTTestCase;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Tests the FlowPanel widget.
*/
@@ -29,4 +32,30 @@
public void testAttachDetachOrder() {
HasWidgetsTester.testAll(new FlowPanel());
}
+
+ public void testClear() {
+ int size = 10;
+ FlowPanel target;
+ List<Widget> children = new ArrayList<Widget>();
+
+ target = new FlowPanel();
+
+ for (int i = 0; i < size; i++) {
+ Widget w = new Label("widget-" + i);
+ target.add(w);
+ children.add(w);
+ }
+
+ RootPanel.get().add(target);
+ for (Widget child : target) {
+ assertNotNull(child.getElement().getPropertyString("__listener"));
+ }
+ assertEquals(10, target.getWidgetCount());
+ target.clear();
+ assertEquals(0, target.getWidgetCount());
+
+ for (Widget child : target) {
+ assertNull(child.getElement().getPropertyString("__listener") == null);
+ }
+ }
}