|
DevGuideJUnitBenchmarking
How to use GWT's JUnit support to create and report on benchmarks to help you optimize your code.
BenchmarkingCompatibility NoteThe Benchmark class has changed in the GWT 1.5 release. For documentation of how to use the benchmarking features of the GWT 1.4 release, see DevGuideJUnitBenchmarking14. IntroductionGWT's JUnit integration provides special support for creating and reporting on benchmarks. Specifically, GWT has introduced a new Benchmark class which provides built-in facilities for common benchmarking needs. To take advantage of benchmarking support, take the following steps:
ExampleTo use the benchmarking classes, start by using junitCreator to create a skeleton JUnit class and launch configuration. > junitCreator -junit ~/tools/lib/junit/junit-3.8.1.jar -module com.example.foo.Foo -eclipse FooBenchmark com.example.foo.test.FooBenchmark Created directory /home/user/workspace/Foo/test/com/example/client/test Created file /home/user/workspace/Foo/test/com/example/foo/client/FooBenchmark.java Created file /home/user/workspace/Foo/FooBenchmark-hosted.launch Created file /home/user/workspace/Foo/FooBenchmark-web.launch Created file /home/user/workspace/Foo/FooBenchmark-hosted Created file /home/user/workspace/Foo/FooBenchmark-web Now, edit FooBenchmark.java:
A Benchmark class differs from a JUnit class in that the test methods will be called repeatedly taking different values each time. The Benchmark class is very flexible in this regard - you can specify as many parameters as you like, whereas you must leave a method definition with no arguments to satisfy the JUnit specification. For each parameter, you will need to provide a single constant containing values to iterate over during the test. GWT provides some built in classes to help define such ranges such as IntRange. For example, this represents the values 512, 1024, 2048, 4096, ... : final IntRange baseRange = new IntRange(512, Integer.MAX_VALUE,
Operator.MULTIPLY, 2);You can create any range of values you like with whatever object values returned, as long as you specify an instance class of Iterable in the annotation for the function parameter. public void testSomething( @RangeField("baseRange") Integer size ) {...}In this case, size is a parameter to the test function, and the range of values are defined by the Iterable instance named baseRange. Here is a full example of a simple Benchmark subclass that compares the execution time of adding an element to a Vector to adding an element to an ArrayList: package com.example.foo.client;
import com.google.gwt.benchmarks.client.Benchmark;
import com.google.gwt.benchmarks.client.IntRange;
import com.google.gwt.benchmarks.client.Operator;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* GWT benchmarks must extend Benchmark.
*/
public class FooBenchmark extends Benchmark {
final IntRange baseRange = new IntRange(512, Integer.MAX_VALUE,
Operator.MULTIPLY, 2);
private List testVector = new Vector();
private List testList = new ArrayList();
/**
* Must refer to a valid module that sources this class.
*/
public String getModuleName() {
return "com.example.foo.Foo";
}
/**
* JUnit requires a method that takes no arguments. It is not used for
* Benchmarking.
*/
public void testSimpleVector() {
}
/**
* Test adding an element to a vector
*/
public void testSimpleVector(@RangeField("baseRange") Integer size)
{
int len = size.intValue();
testVector.clear();
for (int i=0 ; i<len; i++) {
testVector.add(size);
}
}
public void testSimpleList() {
}
/**
* Test adding an element to a List
*/
public void testSimpleList(@RangeField("baseRange") Integer size)
{
int len = size.intValue();
testList.clear();
for (int i=0 ; i<len; i++) {
testList.add(size);
}
}
}Now, run the script FooBenchmark-hosted that was created by junitCreator to run the benchmark. The script will run your code in hosted mode and create a file named report-*.xml. You can view this report with the benchmarkViewer command from command line: For more advanced usage information, see the Benchmark class documentation. |
Sign in to add a comment
For a nice overview of testing and benchmarking, I can recommend the video at http://www.youtube.com/watch?v=OgaFVfO69C8.
One of the things they talk about in the video is the ability to set up distributed client benchmarking. Since we're dealing with browser issues on several platforms, this was exactly what we needed. I'll give a quick overview of how to set this up, since documentation for this is nowhere to be found. Keep in mind that this is using undocumented features!
Introduction
When running GWTTestCases, you have the possibility to pass gwt.args parameters. The following is an example:
GWT tests can be run in a variety of modes (hosted mode, web mode, remote web mode, selenium mode, ..), but the one we're interested in are web mode and remote web mode. Obviously, your benchmarks should never run in hosted mode, since all you'd be benchmarking is Java code.
Web mode can be considered the default choice - it will run the test on the default browser for your platform (IE on Windows machines, Mozilla FF on Linux, ...). However, having the option to benchmark the code on several browsers on different platforms would of course be even better. Enter remote web mode.
Remote Web Mode
In order to use the remote web mode, you should specify the gwt.args parameter -remoteweb followed by some URL(s). These URLs should be pointing to some RMI server (eg. "rmi://localhost") with the registration name of the browser (eg. "/ie6").
How do we set these RMI servers up?
The RMI server you are looking for is the BrowserManagerServer in the com.google.gwt.junit.remote package. You'll need to pass arguments when running this class in the form of 'browser-registration-name' and 'path-to-executable', in the form of pairs. For example, under Windows, one might have the following program parameters:
Note: when starting the browser manager application, make sure no RMI servers are running on port 1099.
Running the distributed test
When the remote browser manager application is running, all you need to do is pass the location argument(s) to the Unit test:
This should find the remote browser managers and run the tests. Obviously, your firewall and security settings should be set up correctly. If you get out-of-memory exceptions, you can increase it by passing flags to the JUnit testcase (-Xmx512M -Xms512M).
Another thing to note is that running Mozilla Firefox requires special attention. For this and more information I happily point you to the BrowserManagerServer? source code.