0N/A/*
2362N/A * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions
0N/A * are met:
0N/A *
0N/A * - Redistributions of source code must retain the above copyright
0N/A * notice, this list of conditions and the following disclaimer.
0N/A *
0N/A * - Redistributions in binary form must reproduce the above copyright
0N/A * notice, this list of conditions and the following disclaimer in the
0N/A * documentation and/or other materials provided with the distribution.
0N/A *
2362N/A * - Neither the name of Oracle nor the names of its
0N/A * contributors may be used to endorse or promote products derived
0N/A * from this software without specific prior written permission.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0N/A * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0N/A * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0N/A * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0N/A * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0N/A * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0N/A * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0N/A * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0N/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
4378N/A/*
4378N/A * This source code is provided to illustrate the usage of a given feature
4378N/A * or technique and has been deliberately simplified. Additional steps
4378N/A * required for a production-quality application, such as security checks,
4378N/A * input validation and proper error handling, might not be present in
4378N/A * this sample code.
4378N/A */
4378N/A
4378N/A
0N/Apackage j2dbench;
0N/A
0N/Apublic abstract class Test extends Option.Enable {
0N/A private DependentLink dependencies;
0N/A
0N/A public Test(Group parent, String nodeName, String description) {
0N/A super(parent, nodeName, description, false);
0N/A }
0N/A
0N/A public void addDependency(Modifier mod) {
0N/A addDependency(mod, null);
0N/A }
0N/A
0N/A public void addDependency(Modifier mod, Modifier.Filter filter) {
0N/A dependencies = DependentLink.add(dependencies, mod, filter);
0N/A }
0N/A
0N/A public void addDependencies(Group g, boolean recursive) {
0N/A addDependencies(g, recursive, null);
0N/A }
0N/A
0N/A public void addDependencies(Group g, boolean recursive,
0N/A Modifier.Filter filter)
0N/A {
0N/A if (g instanceof Modifier) {
0N/A addDependency((Modifier) g, filter);
0N/A }
0N/A for (Node n = g.getFirstChild(); n != null; n = n.getNext()) {
0N/A if (n instanceof Modifier) {
0N/A addDependency((Modifier) n, filter);
0N/A } else if (recursive && n instanceof Group) {
0N/A addDependencies((Group) n, recursive, filter);
0N/A }
0N/A }
0N/A }
0N/A
0N/A public void runTest(TestEnvironment env) {
0N/A if (!env.isStopped() && isEnabled()) {
0N/A dependencies.recurseAndRun(env, this);
0N/A }
0N/A }
0N/A
0N/A public void runOneTest(TestEnvironment env) {
0N/A if (!env.isStopped()) {
0N/A Result result = new Result(this);
0N/A env.erase();
0N/A Object ctx = initTest(env, result);
0N/A result.setModifiers(env.getModifiers());
0N/A try {
0N/A runTestLoop(env, result, ctx);
0N/A } catch (Throwable t) {
0N/A result.setError(t);
0N/A }
0N/A cleanupTest(env, ctx);
0N/A // Skip recording results if we were interrupted before
0N/A // anything interesting happened...
0N/A if (result.getError() != null || result.getNumRuns() != 0) {
0N/A if (J2DBench.printresults.isEnabled()) {
0N/A result.summarize();
0N/A }
0N/A env.record(result);
0N/A }
0N/A ctx = null;
0N/A result = null;
0N/A env.idle(); // Also done after this method returns...
0N/A }
0N/A }
0N/A
0N/A public abstract Object initTest(TestEnvironment env, Result result);
0N/A public abstract void runTest(Object context, int numReps);
0N/A public abstract void cleanupTest(TestEnvironment env, Object context);
0N/A
0N/A public void runTestLoop(TestEnvironment env, Result result, Object ctx) {
0N/A // Prime the pump
0N/A runTest(ctx, 1);
0N/A
0N/A // Determine the number of reps
0N/A int numReps = env.getRepCount();
0N/A if (numReps == 0) {
0N/A numReps = calibrate(env, ctx);
0N/A }
0N/A result.setReps(numReps);
0N/A
0N/A int numRuns = env.getRunCount();
0N/A for (int i = 0; i < numRuns; i++) {
0N/A if (env.idle()) {
0N/A break;
0N/A }
0N/A
0N/A env.sync();
0N/A env.startTiming();
0N/A runTest(ctx, numReps);
0N/A env.sync();
0N/A env.stopTiming();
0N/A result.addTime(env.getTimeMillis());
0N/A
0N/A env.flushToScreen();
0N/A }
0N/A }
0N/A
0N/A public int calibrate(TestEnvironment env, Object ctx) {
0N/A long testTime = env.getTestTime();
0N/A int numReps = 0;
0N/A int totalReps = 0;
0N/A
0N/A // First do one at a time until we get to 1 second elapsed
0N/A // But, if we get to 1000 reps we'll start ramping up our
0N/A // reps per cycle and throwing sync() calls in to make sure
0N/A // we aren't spinning our gears queueing up graphics calls
0N/A env.idle();
0N/A long now = System.currentTimeMillis();
0N/A long startTime = now;
0N/A while (numReps < 1000 && now < startTime + 1000) {
0N/A runTest(ctx, 1);
0N/A numReps++;
0N/A now = System.currentTimeMillis();
0N/A }
0N/A
0N/A // Time to shift gears into an exponential number of tests
0N/A // sync() each time in case batching at a lower level is
0N/A // causing us to spin our gears
0N/A env.sync();
0N/A now = System.currentTimeMillis();
0N/A int reps = 250;
0N/A while (now < startTime + 1000) {
0N/A runTest(ctx, reps);
0N/A env.sync();
0N/A numReps += reps;
0N/A reps *= 2;
0N/A now = System.currentTimeMillis();
0N/A }
0N/A
0N/A // Now keep estimating how many reps it takes to hit our target
0N/A // time exactly, trying it out, and guessing again.
0N/A while (now < startTime + testTime) {
0N/A int estimate = (int) (numReps * testTime / (now - startTime));
0N/A if (estimate <= numReps) {
0N/A estimate = numReps+1;
0N/A }
0N/A runTest(ctx, estimate - numReps);
0N/A numReps = estimate;
0N/A env.sync();
0N/A now = System.currentTimeMillis();
0N/A }
0N/A
0N/A // Now make one last estimate of how many reps it takes to
0N/A // hit the target exactly in case we overshot.
0N/A int estimate = (int) (numReps * testTime / (now - startTime));
0N/A if (estimate < 1) {
0N/A estimate = 1;
0N/A }
0N/A return estimate;
0N/A }
0N/A
0N/A /*
0N/A * Finds a new width (w2) such that
0N/A * (w-2) <= w2 <= w
0N/A * and w2 is not a multiple of 3 (the X step size)
0N/A * and GCD(w2, h) is as small as possible
0N/A */
0N/A static int prevw;
0N/A public static int adjustWidth(int w, int h) {
0N/A int bestv = w;
0N/A int bestw = w;
0N/A boolean verbose = (prevw != w && J2DBench.verbose.isEnabled());
0N/A for (int i = 0; i < 3; i++) {
0N/A int w2 = w-i;
0N/A int u = w2;
0N/A int v = h;
0N/A while (u > 0) {
0N/A if (u < v) { int t = u; u = v; v = t; }
0N/A u -= v;
0N/A }
0N/A if (verbose) {
0N/A System.out.println("w = "+w2+", h = "+h+
0N/A ", w % 3 == "+(w2 % 3)+
0N/A ", gcd(w, h) = "+v);
0N/A }
0N/A if (v < bestv && (w2 % 3) != 0) {
0N/A bestv = v;
0N/A bestw = w2;
0N/A }
0N/A }
0N/A if (verbose) {
0N/A System.out.println("using "+bestw+" (gcd = "+bestv+")");
0N/A prevw = w;
0N/A }
0N/A return bestw;
0N/A }
0N/A
0N/A public String toString() {
0N/A return "Test("+getTreeName()+")";
0N/A }
0N/A
0N/A public static class DependentLink {
0N/A public static DependentLink add(DependentLink d, Modifier mod,
0N/A Modifier.Filter filter)
0N/A {
0N/A DependentLink dl = new DependentLink(mod, filter);
0N/A if (d == null) {
0N/A d = dl;
0N/A } else {
0N/A DependentLink last = d;
0N/A while (last.next != null) {
0N/A last = last.next;
0N/A }
0N/A last.next = dl;
0N/A }
0N/A return d;
0N/A }
0N/A
0N/A private DependentLink next;
0N/A private Modifier mod;
0N/A private Modifier.Filter filter;
0N/A
0N/A private DependentLink(Modifier mod, Modifier.Filter filter) {
0N/A this.mod = mod;
0N/A this.filter = filter;
0N/A }
0N/A
0N/A public Modifier getModifier() {
0N/A return mod;
0N/A }
0N/A
0N/A public Modifier.Filter getFilter() {
0N/A return filter;
0N/A }
0N/A
0N/A public DependentLink getNext() {
0N/A return next;
0N/A }
0N/A
0N/A public void recurseAndRun(TestEnvironment env, Test test) {
0N/A Modifier.Iterator iter = mod.getIterator(env);
0N/A while (iter.hasNext()) {
0N/A Object val = iter.next();
0N/A if (filter == null || filter.isCompatible(val)) {
0N/A mod.modifyTest(env, val);
0N/A if (next == null) {
0N/A test.runOneTest(env);
0N/A env.idle(); // One more time outside of runOneTest()
0N/A } else {
0N/A next.recurseAndRun(env, test);
0N/A }
0N/A mod.restoreTest(env, val);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A}