blob: 170774288038a6e60a29485a0a751ac4e19ff71e [file] [log] [blame]
/*
* Copyright 2008 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.emultest.benchmarks.java.lang;
import com.google.gwt.benchmarks.client.Benchmark;
import com.google.gwt.benchmarks.client.IntRange;
import com.google.gwt.benchmarks.client.Operator;
import com.google.gwt.benchmarks.client.RangeField;
import com.google.gwt.core.client.JavaScriptObject;
/**
* A {@link Benchmark} for {@link StringBuilder StringBuilders}. This includes
* a benchmark from Ray Cromwell that builds display commands in one of two
* ways. One version uses a StringBuilder, and the other uses raw pushes with
* JavaScript. Note that there is no actual DisplayList interface, because
* otherwise the benchmark might have some dynamic dispatch involved. By default
* this benchmarks only the standard <code>StringBuilder</code> and
* <code>StringBuffer</code>. To run the full suite, comment in the alternate
* version of {@link #appendKindsRange}.
*/
public class StringBufferBenchmark extends Benchmark {
/**
* The type of StringBuilder to use for a test.
*/
protected enum SBType {
JS("raw JavaScrpt"), STRBLD("StringBuilder"), STRBUF("StringBuffer");
public String description;
private SBType(String description) {
this.description = description;
}
}
/**
* A DisplayList represented using a native JavaScript array, and updated via
* the JavaScript push() method.
*/
@SuppressWarnings("unused")
private static class JSArrayDisplayList {
private JavaScriptObject jso = JavaScriptObject.createArray();
public void begin() {
jso = JavaScriptObject.createArray();
}
public native void cmd(String cmd) /*-{
this.@com.google.gwt.emultest.benchmarks.java.lang.StringBufferBenchmark$JSArrayDisplayList::jso.push(cmd, 0);
}-*/;
public native void cmd(String cmd, int a) /*-{
this.@com.google.gwt.emultest.benchmarks.java.lang.StringBufferBenchmark$JSArrayDisplayList::jso.push(cmd, 1, a);
}-*/;
public native void cmd(String cmd, int a, int b) /*-{
this.@com.google.gwt.emultest.benchmarks.java.lang.StringBufferBenchmark$JSArrayDisplayList::jso.push(cmd, 2, a, b);
}-*/;
public native void cmd(String cmd, int a, int b, int c) /*-{
this.@com.google.gwt.emultest.benchmarks.java.lang.StringBufferBenchmark$JSArrayDisplayList::jso.push(cmd, 3, a, b, c);
}-*/;
public native String end() /*-{
return this.@com.google.gwt.emultest.benchmarks.java.lang.StringBufferBenchmark$JSArrayDisplayList::jso.join('');
}-*/;
public void fill() {
cmd("F");
}
public void lineTo(int x, int y) {
cmd("L", 0, 0);
}
public void moveTo(int x, int y) {
cmd("M", 0, 0);
}
public void rotate(int angle) {
cmd("R", angle);
}
public void stroke() {
cmd("S");
}
public void translate(int x, int y) {
cmd("T", x, y);
}
}
/**
* A DisplayList represented as a {@link StringBuffer} of commands and
* arguments. To contrast, see {@link JSArrayDisplayList}.
*/
@SuppressWarnings("unused")
private static class StringBufferDisplayList {
private StringBuffer strbld = new StringBuffer();
public void begin() {
strbld = new StringBuffer();
}
public void cmd(String cmd) {
strbld.append(cmd);
strbld.append(0);
}
public void cmd(String cmd, int a) {
strbld.append(cmd);
strbld.append(1);
strbld.append(a);
}
public void cmd(String cmd, int a, int b) {
strbld.append(cmd);
strbld.append(2);
strbld.append(a);
strbld.append(b);
}
public void cmd(String cmd, int a, int b, int c) {
strbld.append(cmd);
strbld.append(3);
strbld.append(a);
strbld.append(b);
strbld.append(c);
}
public String end() {
return strbld.toString();
}
public void fill() {
cmd("F");
}
public void lineTo(int x, int y) {
cmd("L", 0, 0);
}
public void moveTo(int x, int y) {
cmd("M", 0, 0);
}
public void rotate(int angle) {
cmd("R", angle);
}
public void stroke() {
cmd("S");
}
public void translate(int x, int y) {
cmd("T", x, y);
}
}
/**
* A DisplayList represented as a {@link StringBuilder} of commands and
* arguments. To contrast, see {@link JSArrayDisplayList}.
*/
@SuppressWarnings("unused")
private static class StringBuilderDisplayList {
private StringBuilder strbld = new StringBuilder();
public void begin() {
strbld = new StringBuilder();
}
public void cmd(String cmd) {
strbld.append(cmd);
strbld.append(0);
}
public void cmd(String cmd, int a) {
strbld.append(cmd);
strbld.append(1);
strbld.append(a);
}
public void cmd(String cmd, int a, int b) {
strbld.append(cmd);
strbld.append(2);
strbld.append(a);
strbld.append(b);
}
public void cmd(String cmd, int a, int b, int c) {
strbld.append(cmd);
strbld.append(3);
strbld.append(a);
strbld.append(b);
strbld.append(c);
}
public String end() {
return strbld.toString();
}
public void fill() {
cmd("F");
}
public void lineTo(int x, int y) {
cmd("L", 0, 0);
}
public void moveTo(int x, int y) {
cmd("M", 0, 0);
}
public void rotate(int angle) {
cmd("R", angle);
}
public void stroke() {
cmd("S");
}
public void translate(int x, int y) {
cmd("T", x, y);
}
}
private static final String P_CLOSE = "</p>";
private static final String P_OPEN = "<p>";
public final SBType[] appendKindsRange = new SBType[] {
SBType.STRBUF, SBType.STRBLD};
public final IntRange appendTimesRange = new IntRange(32, 4096,
Operator.MULTIPLY, 2);
public final SBType[] displayListKindsRange = new SBType[] {
SBType.STRBUF, SBType.STRBLD, SBType.JS};
public final IntRange displayListTimesRange = new IntRange(32, 4096,
Operator.MULTIPLY, 2);
private volatile String abcde = "abcde";
@Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuiteBenchmarks";
}
/**
* Needed for JUnit.
*/
public void testAppend() {
}
public void testAppend(@RangeField("appendTimesRange")
Integer times, @RangeField("appendKindsRange")
SBType sbtype) {
int outerTimes = 1;
switch (sbtype) {
case STRBLD:
for (int i = 0; i < outerTimes; i++) {
appendWithStringBuilder(times);
}
break;
case STRBUF:
for (int i = 0; i < outerTimes; i++) {
appendWithStringBuffer(times);
}
break;
}
}
/**
* Needed for JUnit.
*/
public void testDisplayList() {
}
/**
* Test creating a display list command sequence.
*/
public void testDisplayList(@RangeField("displayListTimesRange")
Integer times, @RangeField("displayListKindsRange")
SBType sbtype) {
switch (sbtype) {
case JS:
drawWithJSArrayDisplayList(times);
break;
case STRBUF:
drawWithStringBufferDisplayList(times);
break;
case STRBLD:
drawWithStringBuilderDisplayList(times);
break;
}
}
private void appendWithStringBuffer(int times) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < times; i++) {
sb.append(P_OPEN);
sb.append(abcde);
sb.append(P_CLOSE);
}
pretendToUse(sb.toString().length());
}
private void appendWithStringBuilder(int times) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < times; i++) {
sb.append(P_OPEN);
sb.append(abcde);
sb.append(P_CLOSE);
}
pretendToUse(sb.toString().length());
}
/**
* Test drawing commands using JSArrayDisplayList.
*/
private void drawWithJSArrayDisplayList(int times) {
JSArrayDisplayList dl = new JSArrayDisplayList();
dl.begin();
for (int i = 0; i < times; i++) {
// draw a box
dl.translate(50, 50);
dl.rotate(45);
dl.moveTo(0, 0);
dl.lineTo(100, 0);
dl.lineTo(100, 100);
dl.lineTo(0, 100);
dl.lineTo(0, 0);
dl.stroke();
dl.fill();
}
pretendToUse(dl.end().length());
}
/**
* Test drawing commands using {@link StringBufferDisplayList}.
*/
private void drawWithStringBufferDisplayList(int times) {
final StringBufferDisplayList dl = new StringBufferDisplayList();
dl.begin();
for (int i = 0; i < times; i++) {
// draw a box
dl.translate(50, 50);
dl.rotate(45);
dl.moveTo(0, 0);
dl.lineTo(100, 0);
dl.lineTo(100, 100);
dl.lineTo(0, 100);
dl.lineTo(0, 0);
dl.stroke();
dl.fill();
}
pretendToUse(dl.end().length());
}
/**
* Test drawing commands using {@link StringBufferDisplayList}.
*/
private void drawWithStringBuilderDisplayList(int times) {
final StringBuilderDisplayList dl = new StringBuilderDisplayList();
dl.begin();
for (int i = 0; i < times; i++) {
// draw a box
dl.translate(50, 50);
dl.rotate(45);
dl.moveTo(0, 0);
dl.lineTo(100, 0);
dl.lineTo(100, 100);
dl.lineTo(0, 100);
dl.lineTo(0, 0);
dl.stroke();
dl.fill();
}
pretendToUse(dl.end().length());
}
/**
* Make a value appear to be live, so that dead code elimination will not
* strip it out.
*/
private native void pretendToUse(int x) /*-{
$wnd.completelyUselessField = x
}-*/;
}