Adding benchmarks to measure the performance of updating existing tables.
Also refactored WidgetCreationTest into a more generic MicrobenchmarkSurvey,
which runs a set of NanoTests.
You can see the app running here: http://microb.jlabanca-testing.appspot.com/
Review at http://gwt-code-reviews.appspot.com/1419801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10528 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/Microbenchmarks.gwt.xml b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/Microbenchmarks.gwt.xml
index a9c43cc..7b85430 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/Microbenchmarks.gwt.xml
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/Microbenchmarks.gwt.xml
@@ -1,16 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='microbenchmarks'>
- <!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
-
- <!-- Inherit the default GWT style sheet. You can change -->
- <!-- the theme of your GWT application by uncommenting -->
- <!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
- <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
- <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
-
- <!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='com.google.gwt.reference.microbenchmark.client.Microbenchmarks'/>
@@ -18,4 +9,14 @@
<!-- Specify the paths for translatable code -->
<source path='client'/>
+ <!-- Deferred binding for Util. -->
+ <replace-with class="com.google.gwt.reference.microbenchmark.client.UtilImplTrident">
+ <when-type-is class="com.google.gwt.reference.microbenchmark.client.UtilImpl" />
+ <any>
+ <when-property-is name="user.agent" value="ie6" />
+ <when-property-is name="user.agent" value="ie8" />
+ <when-property-is name="user.agent" value="ie9" />
+ </any>
+ </replace-with>
+
</module>
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/EmptyBinder.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/EmptyBinder.java
index e3382c4..0f39b9b 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/EmptyBinder.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/EmptyBinder.java
@@ -25,10 +25,12 @@
*/
public class EmptyBinder extends Composite {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("HTMLPanel UiBinder");
}
+
+ @Override
public Widget make() {
return new EmptyBinder();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/MicrobenchmarkSurvey.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/MicrobenchmarkSurvey.java
new file mode 100644
index 0000000..f37ee1a
--- /dev/null
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/MicrobenchmarkSurvey.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2011 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.reference.microbenchmark.client;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Cookies;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Window.ClosingEvent;
+import com.google.gwt.user.client.Window.ClosingHandler;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.InlineLabel;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * An implementation of {@link Microbenchmark} that surveys multiple timed
+ * tests.
+ */
+public class MicrobenchmarkSurvey implements Microbenchmark {
+
+ /**
+ * A single runnable test that makes up the survey.
+ */
+ static abstract class NanoTest {
+
+ private final String name;
+
+ /**
+ * Construct a new {@link NanoTest}.
+ *
+ * @param name the display name
+ */
+ public NanoTest(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the widget to display in a popup when the user clicks on the test
+ * name.
+ *
+ * @return the popup widget, or null not to show one
+ */
+ public Widget getPopup() {
+ return null;
+ }
+
+ /**
+ * Run the test.
+ */
+ public abstract void runTest();
+
+ /**
+ * Setup the test before starting the timer. Override this method to prepare
+ * the test before it starts running.
+ */
+ public void setup() {
+ // No-op by default.
+ }
+
+ /**
+ * Tear down the test after stopping the timer. Override this method to
+ * cleanup the test after it completes.
+ */
+ public void teardown() {
+ // No-op by default.
+ }
+ }
+
+ /**
+ * A nano test that makes a widget and attaches it to the {@link RootPanel}.
+ */
+ static abstract class WidgetMaker extends NanoTest {
+
+ private final RootPanel root = RootPanel.get();
+ private Widget popupWidget;
+ private Widget w;
+
+ public WidgetMaker(String name) {
+ super(name);
+ }
+
+ @Override
+ public Widget getPopup() {
+ if (popupWidget == null) {
+ popupWidget = make();
+ }
+ return popupWidget;
+ }
+
+ @Override
+ public void runTest() {
+ w = make();
+ root.add(w);
+
+ /*
+ * Force a layout by finding the body's offsetTop and height. We avoid
+ * doing setTimeout(0), which would allow paint to happen, to keep the
+ * test synchronous and because different browsers round that zero to
+ * different minimums. Layout should be the bulk of the time.
+ */
+ Document.get().getBody().getOffsetTop();
+ Document.get().getBody().getOffsetHeight();
+ w.getOffsetHeight();
+ }
+
+ @Override
+ public void teardown() {
+ // Clean up to keep the dom. Attached widgets will affect later tests.
+ root.remove(w);
+ }
+
+ /**
+ * Make the widget to test.
+ *
+ * @return the widget
+ */
+ protected abstract Widget make();
+ }
+
+ /**
+ * A nano test that updates an existing widget that is already attached to the
+ * {@link RootPanel}.
+ *
+ * @param <W> the widget type
+ */
+ static abstract class WidgetUpdater<W extends Widget> extends MicrobenchmarkSurvey.NanoTest {
+
+ private final RootPanel root = RootPanel.get();
+ private W w;
+
+ public WidgetUpdater(String name) {
+ super(name);
+ }
+
+ @Override
+ public Widget getPopup() {
+ return ensureWidget();
+ }
+
+ @Override
+ public void setup() {
+ root.add(ensureWidget());
+ }
+
+ @Override
+ public void runTest() {
+ updateWidget(w);
+ }
+
+ @Override
+ public void teardown() {
+ root.remove(w);
+ }
+
+ /**
+ * Make the widget to test.
+ *
+ * @return the widget
+ */
+ protected abstract W make();
+
+ /**
+ * Update the widget.
+ *
+ * @param w the widget to update
+ */
+ protected abstract void updateWidget(W w);
+
+ private W ensureWidget() {
+ if (w == null) {
+ w = make();
+ }
+ return w;
+ }
+ }
+
+ interface Binder extends UiBinder<Widget, MicrobenchmarkSurvey> {
+ }
+
+ private static final Binder BINDER = GWT.create(Binder.class);
+
+ private static final String COOKIE = "gwt_microb_survey";
+
+ private static final int DEFAULT_INSTANCES = 100;
+
+ public static native void log(String msg) /*-{
+ var logger = $wnd.console;
+ if (logger) {
+ logger.log(msg);
+ if (logger.markTimeline) {
+ logger.markTimeline(msg);
+ }
+ }
+ }-*/;
+
+ @UiField(provided = true)
+ Grid grid;
+ @UiField
+ CheckBox includeLargeWidget;
+ @UiField
+ TextBox number;
+ @UiField
+ Widget root;
+ final String name;
+ private final List<NanoTest> nanos;
+
+ /**
+ * Construct a new {@link MicrobenchmarkSurvey} micro benchmark.
+ *
+ * @param name the name of the benchmark
+ * @param nanos the {@link NanoTest}s that make up the survey
+ */
+ public MicrobenchmarkSurvey(String name, List<NanoTest> nanos) {
+ this.name = name;
+ this.nanos = Collections.unmodifiableList(nanos);
+
+ int instances = DEFAULT_INSTANCES;
+ try {
+ instances = Integer.parseInt(Cookies.getCookie(COOKIE));
+ } catch (NumberFormatException ignored) {
+ }
+
+ // Initialize the grid.
+ grid = new Grid(nanos.size() + 2, 3);
+ grid.setText(0, 0, "median");
+ grid.setText(0, 1, "mean");
+
+ int row = 1;
+ for (final NanoTest nano : nanos) {
+ grid.setText(row, 0, "0");
+ grid.setText(row, 1, "0");
+ InlineLabel a = new InlineLabel();
+ a.setText(nano.getName());
+ a.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ Widget toDisplay = nano.getPopup();
+ if (toDisplay != null) {
+ PopupPanel popup = new PopupPanel(true, true);
+ ScrollPanel container = new ScrollPanel(toDisplay);
+ container.setPixelSize(500, 500);
+ popup.setWidget(container);
+ popup.center();
+ }
+ }
+ });
+ // TODO: popup.
+ grid.setWidget(row, 2, a);
+ row++;
+ }
+
+ // Create the widget.
+ root = BINDER.createAndBindUi(this);
+ number.setVisibleLength(7);
+ number.setValue("" + instances);
+ number.addBlurHandler(new BlurHandler() {
+ public void onBlur(BlurEvent event) {
+ saveInstances();
+ }
+ });
+
+ Window.addWindowClosingHandler(new ClosingHandler() {
+ public void onWindowClosing(ClosingEvent event) {
+ saveInstances();
+ }
+ });
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Widget getWidget() {
+ return root;
+ }
+
+ public void run() {
+ RootPanel root = RootPanel.get();
+
+ // Add a large widget to the root to reflect a typical application.
+ FlowPanel largeWidget = null;
+ if (includeLargeWidget.getValue()) {
+ largeWidget = new FlowPanel();
+ TestWidgetBinder.Maker widgetMaker = new TestWidgetBinder.Maker();
+ for (int i = 0; i < 100; i++) {
+ largeWidget.add(widgetMaker.make());
+ }
+ root.add(largeWidget);
+ }
+
+ int nanosCount = nanos.size();
+ double[] times = new double[nanosCount];
+
+ int column = grid.getColumnCount();
+ grid.resizeColumns(column + 1);
+ grid.setText(0, column, "Run " + (column - 3));
+
+ final int instances = getInstances();
+ boolean forward = false;
+ for (int i = 0; i < instances; ++i) {
+ forward = !forward;
+ for (int m = 0; m < nanosCount; m++) {
+ /*
+ * Alternate the order that we invoke the makers to cancel out the
+ * performance impact of adding elements to the DOM, which would cause
+ * later tests to run more slowly than earlier tests.
+ */
+ NanoTest nano = nanos.get(forward ? m : (nanosCount - 1 - m));
+ nano.setup();
+
+ // Execute the test.
+ log(i + ": " + nano.name);
+ double start = Duration.currentTimeMillis();
+ nano.runTest();
+
+ // Record the end time.
+ double thisTime = Duration.currentTimeMillis() - start;
+ times[m] += thisTime;
+
+ // Cleanup after the test.
+ nano.teardown();
+ }
+ }
+
+ // Record the times.
+ double allTimes = 0;
+ for (int m = 0; m < nanosCount; ++m) {
+ record(m + 1, times[m]);
+ allTimes += times[m];
+ }
+ grid.setText(grid.getRowCount() - 1, grid.getColumnCount() - 1, Util.format(allTimes));
+
+ // Cleanup the dom.
+ if (largeWidget != null) {
+ root.remove(largeWidget);
+ }
+ }
+
+ private int getInstances() {
+ try {
+ int instances = Integer.parseInt(number.getValue());
+ return instances;
+ } catch (NumberFormatException ignored) {
+ return 0;
+ }
+ }
+
+ private void record(int row, double thisTime) {
+ final int columns = grid.getColumnCount();
+ grid.setText(row, columns - 1, Util.format(thisTime));
+
+ double max = 0, min = 0, mean = 0;
+
+ for (int column = 3; column < columns; column++) {
+ double value = Double.parseDouble(grid.getText(row, column));
+ mean += value;
+ max = Math.max(max, value);
+ if (min == 0) {
+ min = max;
+ } else {
+ min = Math.min(min, value);
+ }
+ }
+
+ double range = max - min;
+ double halfRange = range / 2;
+ double median = min + halfRange;
+ grid.setText(row, 0, Util.format(Util.roundToTens(median)));
+
+ mean = mean / (columns - 3);
+ grid.setText(row, 1, Util.format(Util.roundToTens(mean)));
+ }
+
+ @SuppressWarnings("deprecation")
+ private void saveInstances() {
+ String value = number.getValue();
+ Date expires = new Date();
+ expires.setYear(expires.getYear() + 3);
+ Cookies.setCookie(COOKIE, value, expires);
+ }
+}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/WidgetCreation.ui.xml b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/MicrobenchmarkSurvey.ui.xml
similarity index 100%
rename from reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/WidgetCreation.ui.xml
rename to reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/MicrobenchmarkSurvey.ui.xml
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Microbenchmarks.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Microbenchmarks.java
index 367d38d..5669374 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Microbenchmarks.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Microbenchmarks.java
@@ -18,15 +18,16 @@
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.reference.microbenchmark.client.WidgetCreation.Maker;
+import com.google.gwt.reference.microbenchmark.client.MicrobenchmarkSurvey.NanoTest;
+import com.google.gwt.reference.microbenchmark.client.MicrobenchmarkSurvey.WidgetMaker;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.FlowPanel;
@@ -60,20 +61,20 @@
public Microbenchmarks() {
// Add entries for new widget benchmarks here.
- List<Maker> widgetMakers = new ArrayList<Maker>();
- widgetMakers.add(new Maker("SimplePanel") {
+ List<NanoTest> widgetMakers = new ArrayList<NanoTest>();
+ widgetMakers.add(new WidgetMaker("SimplePanel") {
@Override
public Widget make() {
return new SimplePanel();
}
});
- widgetMakers.add(new Maker("FlowPanel") {
+ widgetMakers.add(new WidgetMaker("FlowPanel") {
@Override
public Widget make() {
return new FlowPanel();
}
});
- widgetMakers.add(new Maker("HTMLPanel") {
+ widgetMakers.add(new WidgetMaker("HTMLPanel") {
@Override
public Widget make() {
return new HTMLPanel("");
@@ -96,16 +97,30 @@
widgetMakers.add(new TestManualHTMLPanel.Maker());
widgetMakers.add(new TestWidgetBinder.Maker());
- // Add entries for new table benchmarks here.
- List<Maker> tableMakers = new ArrayList<Maker>();
+ // Add entries for table creation benchmarks here.
+ List<NanoTest> tableMakers = new ArrayList<NanoTest>();
tableMakers.add(new TestCreateTableInnerHtml.Maker());
tableMakers.add(new TestCreateTablePrecreatedInnerHtml.Maker());
tableMakers.add(new TestCreateTableDom.Maker());
tableMakers.add(new TestCreateTableDomWithEvents.Maker());
- benchmarks = new Microbenchmark[2];
- benchmarks[0] = new WidgetCreation("Widget Creation Survey", widgetMakers);
- benchmarks[1] = new WidgetCreation("Table Creation Survey", tableMakers);
+ // Add entries for table update benchmarks here.
+ List<NanoTest> tableUpdaters = new ArrayList<NanoTest>();
+ tableUpdaters.add(new TestCreateTableInnerHtml.Updater());
+ tableUpdaters.add(new TestCreateTablePrecreatedInnerHtml.Updater());
+ tableUpdaters.add(new TestCreateTableDom.Updater());
+ tableUpdaters.add(new TestCreateTableDomWithEvents.Updater());
+
+ // Combine all table tests.
+ List<NanoTest> allTableTests = new ArrayList<MicrobenchmarkSurvey.NanoTest>();
+ allTableTests.addAll(tableMakers);
+ allTableTests.addAll(tableUpdaters);
+
+ benchmarks = new Microbenchmark[4];
+ benchmarks[0] = new MicrobenchmarkSurvey("Widget Creation Survey", widgetMakers);
+ benchmarks[1] = new MicrobenchmarkSurvey("Table Creation and Update Survey", allTableTests);
+ benchmarks[2] = new MicrobenchmarkSurvey("Table Creation Survey", tableMakers);
+ benchmarks[3] = new MicrobenchmarkSurvey("Table Update Survey", tableUpdaters);
}
@UiHandler("listBox")
@@ -119,7 +134,7 @@
final int index = listBox.getSelectedIndex();
UIObject.setVisible(running, true);
button.setEnabled(false);
- DeferredCommand.addCommand(new Command() {
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
double start = Duration.currentTimeMillis();
benchmarks[index].run();
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDom.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDom.java
index 3c9f4e7..31332e6 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDom.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDom.java
@@ -25,13 +25,12 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link TestCreateTableDom.Maker#name} for
- * details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestCreateTableDom extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
- super(Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ super("Create " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ " table via DOM api calls, no widgets");
}
@@ -41,26 +40,43 @@
}
}
+ public static class Updater extends MicrobenchmarkSurvey.WidgetUpdater<TestCreateTableDom> {
+ Updater() {
+ this("Replace rows in " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ + " table via DOM api calls, no widgets");
+ }
+
+ Updater(String name) {
+ super(name);
+ }
+
+ @Override
+ protected TestCreateTableDom make() {
+ return new TestCreateTableDom();
+ }
+
+ @Override
+ protected void updateWidget(TestCreateTableDom w) {
+ // Remove the old rows.
+ int rowCount = w.tableBody.getRows().getLength();
+ for (int i = 0; i < rowCount; i++) {
+ w.tableBody.deleteRow(0);
+ }
+
+ // Add new rows.
+ w.fillTableBodyRows();
+ }
+ }
+
+ private final TableElement table;
+ private final TableSectionElement tableBody;
+
TestCreateTableDom() {
// This table should match the structure defined in Util#createTableHtml().
- TableElement table = Document.get().createTableElement();
- TableSectionElement tbody = Document.get().createTBodyElement();
- table.appendChild(tbody);
- for (int row = 0; row < Util.TABLE_ROW_COUNT; row++) {
- TableRowElement tr = Document.get().createTRElement();
- tbody.appendChild(tr);
- if (row % 2 == 0) {
- tr.addClassName("evenRow");
- } else {
- tr.addClassName("oddRow");
- }
- for (int column = 0; column < Util.TABLE_COLUMN_COUNT; column++) {
- TableCellElement td = Document.get().createTDElement();
- td.setAlign("center");
- td.setVAlign("middle");
- td.appendChild(createCellContents(row, column));
- }
- }
+ table = Document.get().createTableElement();
+ tableBody = Document.get().createTBodyElement();
+ table.appendChild(tableBody);
+ fillTableBodyRows();
setElement(table);
}
@@ -76,4 +92,26 @@
div.setInnerHTML("Cell " + row + ":" + column);
return div;
}
+
+ /**
+ * Fill the table body element with rows.
+ */
+ private void fillTableBodyRows() {
+ for (int row = 0; row < Util.TABLE_ROW_COUNT; row++) {
+ TableRowElement tr = Document.get().createTRElement();
+ tableBody.appendChild(tr);
+ if (row % 2 == 0) {
+ tr.addClassName("evenRow");
+ } else {
+ tr.addClassName("oddRow");
+ }
+ for (int column = 0; column < Util.TABLE_COLUMN_COUNT; column++) {
+ TableCellElement td = Document.get().createTDElement();
+ td.setAlign("center");
+ td.setVAlign("middle");
+ td.appendChild(createCellContents(row, column));
+ tr.appendChild(td);
+ }
+ }
+ }
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDomWithEvents.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDomWithEvents.java
index 0a529b0..11be2be 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDomWithEvents.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableDomWithEvents.java
@@ -20,14 +20,13 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see
- * {@link TestCreateTableDomWithEvents.Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestCreateTableDomWithEvents extends TestCreateTableDom {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
- super(Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ super("Create " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ " table via DOM api calls, no widgets, sink events on each cell");
}
@@ -37,6 +36,18 @@
}
}
+ public static class Updater extends TestCreateTableDom.Updater {
+ Updater() {
+ super("Replace rows in " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ + " table via DOM api calls, no widgets, sink events on each cell");
+ }
+
+ @Override
+ protected TestCreateTableDom make() {
+ return new TestCreateTableDomWithEvents();
+ }
+ }
+
@Override
Element createCellContents(int row, int column) {
Element div = super.createCellContents(row, column);
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableInnerHtml.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableInnerHtml.java
index bc2ba98..10c936e 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableInnerHtml.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTableInnerHtml.java
@@ -15,16 +15,17 @@
*/
package com.google.gwt.reference.microbenchmark.client;
+import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see
- * {@link TestCreateTableInnerHtml.Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestCreateTableInnerHtml extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
- super(Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ super("Create " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ " table via innerHTML built with StringBuilder, no widgets");
}
@@ -34,7 +35,33 @@
}
}
+ public static class Updater extends MicrobenchmarkSurvey.WidgetUpdater<TestCreateTableInnerHtml> {
+ Updater() {
+ super("Update " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ + " tbody via innerHTML built with StringBuilder, no widgets");
+ }
+
+ @Override
+ protected TestCreateTableInnerHtml make() {
+ return new TestCreateTableInnerHtml();
+ }
+
+ @Override
+ protected void updateWidget(TestCreateTableInnerHtml w) {
+ w.replaceAllRows();
+ }
+ }
+
+ private final TableElement table;
+ private final TableSectionElement tableBody;
+
private TestCreateTableInnerHtml() {
- setElement(Util.fromHtml(Util.createTableHtml()));
+ table = Util.fromHtml(Util.createTableHtml()).cast();
+ setElement(table);
+ tableBody = table.getTBodies().getItem(0).cast();
+ }
+
+ private void replaceAllRows() {
+ Util.replaceTableBodyRows(tableBody, Util.createTableRowsHtml());
}
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTablePrecreatedInnerHtml.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTablePrecreatedInnerHtml.java
index 13d0b93..c99a8cf 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTablePrecreatedInnerHtml.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCreateTablePrecreatedInnerHtml.java
@@ -15,20 +15,21 @@
*/
package com.google.gwt.reference.microbenchmark.client;
+import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see
- * {@link TestCreateTablePrecreatedInnerHtml.Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestCreateTablePrecreatedInnerHtml extends Widget {
- public static class Maker extends WidgetCreation.Maker {
-
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
+
private final String tableHtml = Util.createTableHtml();
Maker() {
- super(Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
- + " table via precreated innerHTML String, no widgets");
+ super("Create " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ + " tbody via precreated innerHTML String, no widgets");
}
@Override
@@ -37,7 +38,37 @@
}
}
+ public static class Updater extends
+ MicrobenchmarkSurvey.WidgetUpdater<TestCreateTablePrecreatedInnerHtml> {
+
+ private final String tableRowsHtml = Util.createTableRowsHtml();
+
+ Updater() {
+ super("Update " + Util.TABLE_ROW_COUNT + "x" + Util.TABLE_COLUMN_COUNT
+ + " table via precreated innerHTML String, no widgets");
+ }
+
+ @Override
+ protected TestCreateTablePrecreatedInnerHtml make() {
+ return new TestCreateTablePrecreatedInnerHtml(Util.createTableHtml());
+ }
+
+ @Override
+ protected void updateWidget(TestCreateTablePrecreatedInnerHtml w) {
+ w.replaceAllRows(tableRowsHtml);
+ }
+ }
+
+ private final TableElement table;
+ private final TableSectionElement tableBody;
+
private TestCreateTablePrecreatedInnerHtml(String tableHtml) {
- setElement(Util.fromHtml(tableHtml));
+ table = Util.fromHtml(tableHtml).cast();
+ setElement(table);
+ tableBody = table.getTBodies().getItem(0).cast();
+ }
+
+ private void replaceAllRows(String tableRowsHtml) {
+ Util.replaceTableBodyRows(tableBody, tableRowsHtml);
}
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCursorDomCrawl.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCursorDomCrawl.java
index 0fbbe18..0717a69 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCursorDomCrawl.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestCursorDomCrawl.java
@@ -6,13 +6,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestCursorDomCrawl extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via innerHTML, no widgets, get children by idealized crawl");
}
+
+ @Override
public Widget make() {
return new TestCursorDomCrawl();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomBinder.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomBinder.java
index 9488543..32a9d7d 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomBinder.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomBinder.java
@@ -24,14 +24,16 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestDomBinder extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via UiBinder, no widgets");
}
+
+ @Override
public Widget make() {
return new TestDomBinder();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlById.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlById.java
index 14ad279..207e673 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlById.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlById.java
@@ -22,13 +22,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestDomInnerHtmlById extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via innerHTML, no widgets, getElementById");
}
+
+ @Override
public Widget make() {
return new TestDomInnerHtmlById();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlQuerySelectorAll.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlQuerySelectorAll.java
index 868fc50..f7bfb79 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlQuerySelectorAll.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomInnerHtmlQuerySelectorAll.java
@@ -22,13 +22,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestDomInnerHtmlQuerySelectorAll extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via innerHTML, no widgets, querySelectorAll");
}
+
+ @Override
public Widget make() {
return new TestDomInnerHtmlQuerySelectorAll();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomViaApi.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomViaApi.java
index e16ba30..6699f82 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomViaApi.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestDomViaApi.java
@@ -21,14 +21,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestDomViaApi extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via DOM api calls, no widgets");
}
+ @Override
public Widget make() {
return new TestDomViaApi();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyCursorDomCrawl.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyCursorDomCrawl.java
index 20a09bd..4611d76 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyCursorDomCrawl.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyCursorDomCrawl.java
@@ -6,13 +6,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestEmptyCursorDomCrawl extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Empty UI via innerHTML, no widgets, get children by idealized crawl");
}
+
+ @Override
public Widget make() {
return new TestEmptyCursorDomCrawl();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDom.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDom.java
index b0a47be9..e642b7f 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDom.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDom.java
@@ -22,13 +22,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestEmptyDom extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Empty UI via innerHTML, no widgets, get children by id");
}
+
+ @Override
public Widget make() {
return new TestEmptyDom();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDomViaApi.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDomViaApi.java
index d3051fa..38672e7 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDomViaApi.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyDomViaApi.java
@@ -21,14 +21,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestEmptyDomViaApi extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Empty UI via DOM api calls, no widgets");
}
+ @Override
public Widget make() {
return new TestEmptyDomViaApi();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyRealisticDomCrawl.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyRealisticDomCrawl.java
index e6d3e15..909bd68 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyRealisticDomCrawl.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestEmptyRealisticDomCrawl.java
@@ -6,13 +6,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestEmptyRealisticDomCrawl extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Empty UI via innerHTML, no widgets, get children by nav from root");
}
+
+ @Override
public Widget make() {
return new TestEmptyRealisticDomCrawl();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestFlows.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestFlows.java
index c46b4f6..5d7acbc 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestFlows.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestFlows.java
@@ -6,13 +6,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestFlows extends Composite {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via FlowPanels (DIVs) and InlineLabels (SPANs)");
}
+
+ @Override
public Widget make() {
return new TestFlows();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestManualHTMLPanel.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestManualHTMLPanel.java
index 3be721f..d3d813d 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestManualHTMLPanel.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestManualHTMLPanel.java
@@ -7,13 +7,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestManualHTMLPanel extends Composite {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via typical manual HTMLPanel usage");
}
+
+ @Override
public Widget make() {
return new TestManualHTMLPanel();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestRealisticDomCrawl.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestRealisticDomCrawl.java
index 7100b63..e8facdc 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestRealisticDomCrawl.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestRealisticDomCrawl.java
@@ -6,13 +6,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestRealisticDomCrawl extends Widget {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI via innerHTML, no widgets, get children by nav from root");
}
+
+ @Override
public Widget make() {
return new TestRealisticDomCrawl();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestWidgetBinder.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestWidgetBinder.java
index 1b29c99..6dc3a44 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestWidgetBinder.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/TestWidgetBinder.java
@@ -24,13 +24,15 @@
import com.google.gwt.user.client.ui.Widget;
/**
- * Run by {@link WidgetCreation}, see {@link Maker#name} for details.
+ * Run by {@link MicrobenchmarkSurvey}, see name for details.
*/
public class TestWidgetBinder extends Composite {
- public static class Maker extends WidgetCreation.Maker {
+ public static class Maker extends MicrobenchmarkSurvey.WidgetMaker {
Maker() {
super("Text heavy UI with HTMLPanel via UiBinder");
}
+
+ @Override
public Widget make() {
return new TestWidgetBinder();
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Util.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Util.java
index 6e87528..469db17 100644
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Util.java
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/Util.java
@@ -1,10 +1,12 @@
package com.google.gwt.reference.microbenchmark.client;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.i18n.client.NumberFormat;
class Util {
@@ -44,13 +46,25 @@
+ "Div anon end</div>"
+ "Div root end";
+ private static int uniqueId = 0;
+ private static UtilImpl impl = GWT.create(UtilImpl.class);
+
static void addText(Element elm, String text) {
elm.appendChild(Document.get().createTextNode(text));
}
static String createTableHtml() {
StringBuilder sb = new StringBuilder();
- sb.append("<table>");
+ sb.append("<table><tbody>");
+ sb.append(createTableRowsHtml());
+ sb.append("</tbody></table>");
+ return sb.toString();
+ }
+
+ static String createTableRowsHtml() {
+ // Assign a unique ID to ensure that we actually change the content.
+ uniqueId++;
+ StringBuilder sb = new StringBuilder();
for (int row = 0; row < Util.TABLE_ROW_COUNT; row++) {
if (row % 2 == 0) {
sb.append("<tr class=\"evenRow\">");
@@ -59,12 +73,11 @@
}
for (int column = 0; column < Util.TABLE_COLUMN_COUNT; column++) {
sb.append("<td align=\"center\" valign=\"middle\"><div>");
- sb.append("Cell " + row + ":" + column);
+ sb.append(uniqueId + " - Cell " + row + ":" + column);
sb.append("</div></td>");
}
sb.append("</tr>");
}
- sb.append("</table>");
return sb.toString();
}
@@ -90,6 +103,16 @@
return root.querySelectorAll(selector);
}-*/;
+ /**
+ * Replace all of the rows in the specified tbody.
+ *
+ * @param tbody the tbody element
+ * @param rowHtml the HTML that represents the rows
+ */
+ static void replaceTableBodyRows(TableSectionElement tbody, String rowHtml) {
+ impl.replaceTableBodyRows(tbody, rowHtml);
+ }
+
static long roundToTens(double median) {
return Math.round(median/10)*10;
}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImpl.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImpl.java
new file mode 100644
index 0000000..5e50ef5
--- /dev/null
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImpl.java
@@ -0,0 +1,13 @@
+package com.google.gwt.reference.microbenchmark.client;
+
+import com.google.gwt.dom.client.TableSectionElement;
+
+/**
+ * Implementation of {@link Util}.
+ */
+class UtilImpl {
+
+ void replaceTableBodyRows(TableSectionElement tbody, String rowHtml) {
+ tbody.setInnerHTML(rowHtml);
+ }
+}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImplTrident.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImplTrident.java
new file mode 100644
index 0000000..efe9429
--- /dev/null
+++ b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/UtilImplTrident.java
@@ -0,0 +1,44 @@
+package com.google.gwt.reference.microbenchmark.client;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableSectionElement;
+
+/**
+ * IE implementation of Util.
+ */
+class UtilImplTrident extends UtilImpl {
+
+ private final com.google.gwt.user.client.Element tmpElem = Document.get().createDivElement()
+ .cast();
+
+ /**
+ * IE doesn't support innerHTML on tbody, nor does it support removing or
+ * replacing a tbody. The only solution is to remove and replace the rows
+ * themselves.
+ */
+ @Override
+ void replaceTableBodyRows(TableSectionElement tbody, String rowHtml) {
+ // Remove all children.
+ Element child = tbody.getFirstChildElement();
+ while (child != null) {
+ Element next = child.getNextSiblingElement();
+ tbody.removeChild(child);
+ child = next;
+ }
+
+ // Convert the row html to child elements.
+ tmpElem.setInnerHTML("<table><tbody>" + rowHtml + "</tbody></table>");
+ TableElement tableElem = tmpElem.getFirstChildElement().cast();
+ TableSectionElement newRows = tableElem.getTBodies().getItem(0);
+
+ // Add new child elements.
+ child = newRows.getFirstChildElement();
+ while (child != null) {
+ Element next = child.getNextSiblingElement();
+ tbody.appendChild(child);
+ child = next;
+ }
+ }
+}
diff --git a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/WidgetCreation.java b/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/WidgetCreation.java
deleted file mode 100644
index fb7f183..0000000
--- a/reference/Microbenchmarks/src/com/google/gwt/reference/microbenchmark/client/WidgetCreation.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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.reference.microbenchmark.client;
-
-import com.google.gwt.core.client.Duration;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.Document;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.Cookies;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.Window.ClosingEvent;
-import com.google.gwt.user.client.Window.ClosingHandler;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Compares various widget creation strategies.
- */
-public class WidgetCreation implements Microbenchmark {
- static abstract class Maker {
- final String name;
-
- Maker(String name) {
- this.name = name;
- }
-
- abstract Widget make();
- }
-
- interface Binder extends UiBinder<Widget, WidgetCreation> {}
-
- private static final Binder BINDER = GWT.create(Binder.class);
-
- private static final String COOKIE = "gwt_microb_widgetCreation";
-
- private static final int DEFAULT_INSTANCES = 100;
-
- public static native void log(String msg) /*-{
- var logger = $wnd.console;
- if (logger) {
- logger.log(msg);
- if(logger.markTimeline) {
- logger.markTimeline(msg);
- }
- }
- }-*/;
-
- @UiField(provided = true) Grid grid;
- @UiField CheckBox includeLargeWidget;
- @UiField TextBox number;
- @UiField Widget root;
- final String name;
- final List<Maker> makers;
-
- /**
- * Construct a new {@link WidgetCreation} micro benchmark.
- *
- * @param name the name of the benchmark
- * @param makers the makers for the widget strategies
- */
- public WidgetCreation(String name, List<Maker> makers) {
- this.name = name;
- this.makers = Collections.unmodifiableList(makers);
-
- int instances = DEFAULT_INSTANCES;
- try {
- instances = Integer.parseInt(Cookies.getCookie(COOKIE));
- } catch (NumberFormatException ignored) {
- }
-
- // Initialize the grid.
- grid = new Grid(makers.size() + 2, 3);
- grid.setText(0, 0, "median");
- grid.setText(0, 1, "mean");
-
- int row = 1;
- for (Maker m : makers) {
- grid.setText(row, 0, "0");
- grid.setText(row, 1, "0");
- InlineLabel a = new InlineLabel();
- a.setText(m.name);
- a.setTitle(Util.outerHtml(m.make().getElement()));
- grid.setWidget(row, 2, a);
- row++;
- }
-
- // Create the widget.
- root = BINDER.createAndBindUi(this);
- number.setVisibleLength(7);
- number.setValue("" + instances);
- number.addBlurHandler(new BlurHandler() {
- public void onBlur(BlurEvent event) {
- saveInstances();
- }
- });
-
- Window.addWindowClosingHandler(new ClosingHandler() {
- public void onWindowClosing(ClosingEvent event) {
- saveInstances();
- }
- });
- }
-
- public String getName() {
- return name;
- }
-
- public Widget getWidget() {
- return root;
- }
-
- public void run() {
- RootPanel root = RootPanel.get();
-
- // Add a large widget to the root to reflect a typical application.
- FlowPanel largeWidget = null;
- if (includeLargeWidget.getValue()) {
- largeWidget = new FlowPanel();
- TestWidgetBinder.Maker widgetMaker = new TestWidgetBinder.Maker();
- for (int i = 0; i < 100; i++) {
- largeWidget.add(widgetMaker.make());
- }
- root.add(largeWidget);
- }
-
- int makersCount = makers.size();
- double[] times = new double[makersCount];
-
- int column = grid.getColumnCount();
- grid.resizeColumns(column + 1);
- grid.setText(0, column, "Run " + (column - 3));
-
- final int instances = getInstances();
- boolean forward = false;
- for (int i = 0; i < instances; ++i) {
- forward = !forward;
- for (int m = 0; m < makersCount; m++) {
- /*
- * Alternate the order that we invoke the makers to cancel out the
- * performance impact of adding elements to the DOM, which would cause
- * later tests to run more slowly than earlier tests.
- */
- Maker maker = makers.get(forward ? m : (makersCount - 1 - m));
- log(i + ": " + maker.name);
- double start = Duration.currentTimeMillis();
- Widget w = maker.make();
- root.add(w);
-
- /*
- * Force a layout by finding the body's offsetTop and height. We avoid
- * doing setTimeout(0), which would allow paint to happen, to keep the
- * test synchronous and because different browsers round that zero to
- * different minimums. Layout should be the bulk of the time.
- */
- Document.get().getBody().getOffsetTop();
- Document.get().getBody().getOffsetHeight();
- w.getOffsetHeight();
-
- double thisTime = Duration.currentTimeMillis() - start;
- times[m] += thisTime;
-
- // Clean up to keep the dom. Attached widgets will affect later tests.
- root.remove(w);
- }
- }
-
- // Record the times.
- double allTimes = 0;
- for (int m = 0; m < makersCount; ++m) {
- record(m + 1, times[m]);
- allTimes += times[m];
- }
- grid.setText(grid.getRowCount() - 1, grid.getColumnCount() - 1, Util.format(allTimes));
-
- // Cleanup the dom.
- if (largeWidget != null) {
- root.remove(largeWidget);
- }
- }
-
- private int getInstances() {
- try {
- int instances = Integer.parseInt(number.getValue());
- return instances;
- } catch (NumberFormatException ignored) {
- return 0;
- }
- }
-
- private void record(int row, double thisTime) {
- final int columns = grid.getColumnCount();
- grid.setText(row, columns - 1, Util.format(thisTime));
-
- double max = 0, min = 0, mean = 0;
-
- for (int column = 3; column < columns; column++) {
- double value = Double.parseDouble(grid.getText(row, column));
- mean += value;
- max = Math.max(max, value);
- if (min == 0) {
- min = max;
- } else {
- min = Math.min(min, value);
- }
- }
-
- double range = max - min;
- double halfRange = range / 2;
- double median = min + halfRange;
- grid.setText(row, 0, Util.format(Util.roundToTens(median)));
-
- mean = mean / (columns - 3);
- grid.setText(row, 1, Util.format(Util.roundToTens(mean)));
- }
-
- @SuppressWarnings("deprecation")
- private void saveInstances() {
- String value = number.getValue();
- Date expires = new Date();
- expires.setYear(expires.getYear() + 3);
- Cookies.setCookie(COOKIE, value, expires);
- }
-}