GWT 2.0.3

com.google.gwt.benchmarks.client
Class Benchmark

java.lang.Object
  extended by junit.framework.Assert
      extended by junit.framework.TestCase
          extended by com.google.gwt.junit.client.GWTTestCase
              extended by com.google.gwt.benchmarks.client.Benchmark
All Implemented Interfaces:
junit.framework.Test

public abstract class Benchmark
extends GWTTestCase

A type of GWTTestCase which specifically records performance results. Benchmarks have additional functionality above and beyond GWT's JUnit support for standard TestCases.

Reporting

In a single JUnit run, the results of all executed benchmarks are collected and stored in an XML report viewable with the benchmarkViewer.

Permutations

GWT supports test methods that have parameters. GWT will execute each benchmark method multiple times in order to exhaustively test all the possible combinations of parameter values. All of your test method parameters must be annotated with a Range annotation such as RangeField or RangeEnum. For example,

 
 public void testArrayListRemoves(
   @RangeEnum(Position.class) Position where, 
   @RangeField("insertRemoveRange") Integer size) { ... 
 }
 

Timing

Notes

Please note that Benchmarks do not currently support asynchronous testing mode. Calling GWTTestCase.delayTestFinish(int) or GWTTestCase.finishTest() will result in an UnsupportedOperationException.

Examples of benchmarking in action

A simple benchmark example

AllocBenchmark is an example of a basic benchmark that doesn't take advantage of most of benchmarking's advanced features.
public class AllocBenchmark extends Benchmark {

  private static final int numAllocs = 1000;

  @Override
  public String getModuleName() {
    return "com.google.gwt.examples.Benchmarks";
  }

  /**
   * Allocates java.lang.Object in a for loop 1,000 times.
   *
   * The current version of the compiler lifts the declaration of obj outside
   * of this loop and also does constant folding of numAllocs.
   * Also, this loop allocs the GWT JS mirror for java.lang.Object
   * NOT an empty JS object, for example.
   *
   */
  public void testJavaObjectAlloc() {
    for ( int i = 0; i < numAllocs; ++i ) {
      Object obj = new Object();
    }
  }

  /**
   * Compares GWT mirror allocations of java.lang.Object to an empty JS object.
   */
  public native void testJsniObjectAlloc1() /*-{
    for (var i = 0; i < @com.google.gwt.examples.benchmarks.AllocBenchmark::numAllocs; ++i ) {
      var obj = {}; // An empty JS object alloc
    }
  }-*/;

  /**
   * Like version 1, but also folds the constant being used in the iteration.
   */
  public native void testJsniObjectAlloc2() /*-{
    for (var i = 0; i < 1000; ++i ) {
      var obj = {}; // An empty JS object alloc
    }
  }-*/;

  /**
   * Like version 2, but hoists the variable declaration from the loop.
   */
  public native void testJsniObjectAlloc3() /*-{
    var obj;
    for (var i = 0; i < 1000; ++i ) {
      obj = {}; // An empty JS object alloc
    }
  }-*/;

  /**
   * Like version 3, but counts down (and in a slightly different range).
   */
  public native void testJsniObjectAlloc4() /*-{
    var obj;
    for (var i = 1000; i > 0; --i ) {
      obj = {}; // An empty JS object alloc
    }
  }-*/;
}

An advanced benchmark example

ArrayListBenchmark is a more sophisticated example of benchmarking. It demonstrates the use of Setup and Teardown test methods, parameterized test methods, and time limits.
public class ArrayListBenchmark extends Benchmark {

  private static final int PRIME = 3001;

  /**
   * The various positions that data can be inserted into a list.
   */
  protected enum Position {

    BEGIN("at the beginning"), EXPLICIT_END("explicitly at the end"), IMPLICIT_END(
        "implicitly at the end"), VARIED("in varied locations");

    private String label;

    /**
     * Constructor for Position.
     * 
     * @param label a not null label describing this
     *          Position.
     */
    Position(String label) {
      this.label = label;
    }

    /**
     * Returns the textual description for the position.
     * 
     * @return a not null description.
     */
    @Override
    public String toString() {
      return label;
    }
  }

  protected final List explicitPositions = Arrays.asList(
      Position.BEGIN, Position.EXPLICIT_END, Position.VARIED);

  protected final IntRange insertRemoveRange = new IntRange(64,
      Integer.MAX_VALUE, Operator.MULTIPLY, 2);

  protected final IntRange baseRange = new IntRange(512, Integer.MAX_VALUE,
      Operator.MULTIPLY, 2);

  List list;

  int index = 0;

  @Override
  public String getModuleName() {
    return "com.google.gwt.emultest.EmulSuite";
  }

  /**
   * Appends size items to an empty {@code List}.
   * 
   * @param size the size of the {@code List}
   */
  @Setup("beginListAdds")
  public void testListAdds(@RangeField("baseRange")
  Integer size) {
    int num = size.intValue();
    for (int i = 0; i < num; i++) {
      list.add("hello");
    }
  }

  // Required for JUnit
  public void testListAdds() {
  }

  /**
   * Performs size gets on a {@code List} of size,
   * size.
   * 
   * @param size the size of the {@code List}
   */
  @Setup("beginListGets")
  public void testListGets(@RangeField("baseRange")
  Integer size) {
    int num = size.intValue();
    for (int i = 0; i < num; i++) {
      list.get(i);
    }
  }

  // Required for JUnit
  public void testListGets() {
  }

  /**
   * Performs size inserts at position, where, on
   * an empty List.
   * 
   * @param where Where the inserts happen
   * @param size The size of the List
   * 
   */
  @Setup("beginListInserts")
  public void testListInserts(@RangeEnum(Position.class)
  Position where, @RangeField("insertRemoveRange")
  Integer size) {
    insertIntoCollection(size, where, list);
  }

  // Required for JUnit
  public void testListInserts() {
  }

  /**
   * Performs size removes at position, where, on
   * an ArrayList of size, size.
   * 
   * @param where Where the inserts happen
   * @param size The size of the List
   */
  @Setup("beginListRemoves")
  public void testListRemoves(@RangeField("explicitPositions")
  Position where, @RangeField("insertRemoveRange")
  Integer size) {
    removeFromCollection(size, where, list);
  }

  // Required for JUnit
  public void testListRemoves() {
  }

  /**
   * Creates a new empty List.
   * 
   * @return a not null, empty List
   */
  protected List newList() {
    return new ArrayList();
  }

  void beginListAdds(Integer size) {
    list = newList();
  }

  void beginListGets(Integer size) {
    createList(size);
  }

  void beginListInserts(Position where, Integer size) {
    list = newList();
    index = 0;
  }

  void beginListRemoves(Position where, Integer size) {
    beginListInserts(where, size);
    testListInserts(where, size);
  }

  private void createList(Integer size) {
    beginListAdds(size);
    testListAdds(size);
  }

  private void insertIntoCollection(Integer size, Position where, List l) {
    int num = size.intValue();
    for (int i = 0; i < num; i++) {
      if (where == Position.IMPLICIT_END) {
        l.add("hello");
      } else if (where == Position.BEGIN) {
        l.add(0, "hello");
      } else if (where == Position.EXPLICIT_END) {
        l.add(l.size(), "hello");
      } else if (where == Position.VARIED) {
        l.add(index, "hello");
        index += PRIME;
        index %= l.size();
      }
    }
  }

  private int removeFromCollection(Integer size, Position where, List l) {
    int num = size.intValue();
    for (int i = 0; i < num; i++) {
      if (where == Position.IMPLICIT_END) {
        throw new RuntimeException("cannot remove from the end implicitly");
      } else if (where == Position.BEGIN) {
        l.remove(0);
      } else if (where == Position.EXPLICIT_END) {
        l.remove(l.size() - 1);
      } else if (where == Position.VARIED) {
        l.remove(index);
        index += PRIME;
        int currentSize = l.size();
        if (currentSize > 0) {
          index %= l.size();
        }
      }
    }
    return index;
  }
}


Nested Class Summary
static class Benchmark.BenchmarkStrategy
          The JUnitShell.Strategy used for benchmarking.
 
Nested classes/interfaces inherited from class com.google.gwt.junit.client.GWTTestCase
GWTTestCase.BaseStrategy, GWTTestCase.TestModuleInfo
 
Field Summary
static java.lang.String REPORT_PATH
          The name of the system property that specifies the location where benchmark reports are both written to and read from.
 
Fields inherited from class com.google.gwt.junit.client.GWTTestCase
ALL_GWT_TESTS, testResult
 
Constructor Summary
Benchmark()
           
 
Method Summary
protected  com.google.gwt.junit.JUnitShell.Strategy createStrategy()
          Creates the test strategy to use (see GWTTestCase.getStrategy()).
protected  void runTest()
          Runs the test via the BenchmarkShell environment.
protected  boolean supportsAsync()
          Benchmarks do not support asynchronous mode.
 
Methods inherited from class com.google.gwt.junit.client.GWTTestCase
addCheckpoint, catchExceptions, clearCheckpoints, delayTestFinish, finishTest, getAllTestModuleNames, getCheckpoints, getModuleCount, getModuleName, getStrategy, getSyntheticModuleName, getTestsForModule, gwtSetUp, gwtTearDown, run, setName, setUp, tearDown
 
Methods inherited from class junit.framework.TestCase
countTestCases, createResult, getName, run, runBare, toString
 
Methods inherited from class junit.framework.Assert
assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertEquals, assertFalse, assertFalse, assertNotNull, assertNotNull, assertNotSame, assertNotSame, assertNull, assertNull, assertSame, assertSame, assertTrue, assertTrue, fail, fail
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

REPORT_PATH

public static final java.lang.String REPORT_PATH
The name of the system property that specifies the location where benchmark reports are both written to and read from. Its value is com.google.gwt.junit.reportPath. If this system property is not set, the path defaults to the user's current working directory.

See Also:
Constant Field Values
Constructor Detail

Benchmark

public Benchmark()
Method Detail

createStrategy

protected com.google.gwt.junit.JUnitShell.Strategy createStrategy()
Description copied from class: GWTTestCase
Creates the test strategy to use (see GWTTestCase.getStrategy()).

Overrides:
createStrategy in class GWTTestCase

runTest

protected final void runTest()
                      throws java.lang.Throwable
Runs the test via the BenchmarkShell environment. Do not override or call this method.

Overrides:
runTest in class GWTTestCase
Throws:
java.lang.Throwable

supportsAsync

protected final boolean supportsAsync()
Benchmarks do not support asynchronous mode.

Overrides:
supportsAsync in class GWTTestCase

GWT 2.0.3