blob: 149acc53202c76f4280cae9ddae4a6f27c92e5ba [file] [log] [blame]
/*
* 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.dom.client.Document;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
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.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import java.util.ArrayList;
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();
}
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.markTimeline) {
logger.markTimeline(msg);
}
}-*/;
final Grid grid;
final TextBox number;
final List<Maker> makers;
{
List<Maker> makeMakers = new ArrayList<Maker>();
makeMakers.add(new Maker("SimplePanel") {
public Widget make() {
return new SimplePanel();
}
});
makeMakers.add(new Maker("FlowPanel") {
public Widget make() {
return new FlowPanel();
}
});
makeMakers.add(new Maker("HTMLPanel") {
public Widget make() {
return new HTMLPanel("");
}
});
makeMakers.add(new EmptyBinder.Maker());
makeMakers.add(new TestEmptyDomViaApi.Maker());
makeMakers.add(new TestEmptyDom.Maker());
makeMakers.add(new TestEmptyCursorDomCrawl.Maker());
makeMakers.add(new TestEmptyRealisticDomCrawl.Maker());
makeMakers.add(new TestDomViaApi.Maker());
makeMakers.add(new TestDomInnerHtmlById.Maker());
if (Util.hasQSA) {
makeMakers.add(new TestDomInnerHtmlQuerySelectorAll.Maker());
}
makeMakers.add(new TestCursorDomCrawl.Maker());
makeMakers.add(new TestRealisticDomCrawl.Maker());
makeMakers.add(new TestDomBinder.Maker());
makeMakers.add(new TestFlows.Maker());
makeMakers.add(new TestManualHTMLPanel.Maker());
makeMakers.add(new TestWidgetBinder.Maker());
makers = Collections.unmodifiableList(makeMakers);
}
final private FlowPanel root;
public WidgetCreation() {
int instances = DEFAULT_INSTANCES;
try {
instances = Integer.parseInt(Cookies.getCookie(COOKIE));
} catch (NumberFormatException ignored) {
}
number = new TextBox();
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();
}
});
grid = new Grid(makers.size() + 2, 3);
grid.setText(0, 0, "50%");
grid.setText(0, 1, "m");
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++;
}
root = new FlowPanel();
HTMLPanel l = new HTMLPanel(
"<b>Time for creating, attaching and detaching "
+ "<span id='number'></span> instances, in MS<br><br></b>");
l.addAndReplaceElement(number, "number");
root.add(l);
root.add(grid);
}
public String getName() {
return "Widget Creation Survey";
}
public Widget getWidget() {
return root;
}
public void run() {
RootPanel root = RootPanel.get();
Widget[] widgets = new Widget[getInstances()];
grid.resizeColumns(grid.getColumnCount() + 1);
int row = 1;
double allTimes = 0;
for (Maker maker : makers) {
log(maker.name);
double start = Duration.currentTimeMillis();
for (int i = 0; i < getInstances(); ++i) {
widgets[i] = maker.make();
root.add(widgets[i]);
}
/*
* Force a layout by finding the body's offsetTop. 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();
double thisTime = Duration.currentTimeMillis() - start;
record(row, thisTime);
allTimes += thisTime;
// Clean up to keep the dom a reasonable size.
for (int i = 0; i < getInstances(); ++i) {
root.remove(widgets[i]);
}
row++;
}
grid.setText(row, grid.getColumnCount() - 1, Util.format(allTimes));
}
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);
}
}