1 /* 2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 package j2dbench; 42 43 public abstract class Test extends Option.Enable { 44 private DependentLink dependencies; 45 Test(Group parent, String nodeName, String description)46 public Test(Group parent, String nodeName, String description) { 47 super(parent, nodeName, description, false); 48 } 49 addDependency(Modifier mod)50 public void addDependency(Modifier mod) { 51 addDependency(mod, null); 52 } 53 addDependency(Modifier mod, Modifier.Filter filter)54 public void addDependency(Modifier mod, Modifier.Filter filter) { 55 dependencies = DependentLink.add(dependencies, mod, filter); 56 } 57 addDependencies(Group g, boolean recursive)58 public void addDependencies(Group g, boolean recursive) { 59 addDependencies(g, recursive, null); 60 } 61 addDependencies(Group g, boolean recursive, Modifier.Filter filter)62 public void addDependencies(Group g, boolean recursive, 63 Modifier.Filter filter) 64 { 65 if (g instanceof Modifier) { 66 addDependency((Modifier) g, filter); 67 } 68 for (Node n = g.getFirstChild(); n != null; n = n.getNext()) { 69 if (n instanceof Modifier) { 70 addDependency((Modifier) n, filter); 71 } else if (recursive && n instanceof Group) { 72 addDependencies((Group) n, recursive, filter); 73 } 74 } 75 } 76 runTest(TestEnvironment env)77 public void runTest(TestEnvironment env) { 78 if (!env.isStopped() && isEnabled()) { 79 dependencies.recurseAndRun(env, this); 80 } 81 } 82 runOneTest(TestEnvironment env)83 public void runOneTest(TestEnvironment env) { 84 if (!env.isStopped()) { 85 Result result = new Result(this); 86 env.erase(); 87 Object ctx = initTest(env, result); 88 result.setModifiers(env.getModifiers()); 89 try { 90 runTestLoop(env, result, ctx); 91 } catch (Throwable t) { 92 result.setError(t); 93 } 94 cleanupTest(env, ctx); 95 // Skip recording results if we were interrupted before 96 // anything interesting happened... 97 if (result.getError() != null || result.getNumRuns() != 0) { 98 if (J2DBench.printresults.isEnabled()) { 99 result.summarize(); 100 } 101 env.record(result); 102 } 103 ctx = null; 104 result = null; 105 env.idle(); // Also done after this method returns... 106 } 107 } 108 initTest(TestEnvironment env, Result result)109 public abstract Object initTest(TestEnvironment env, Result result); runTest(Object context, int numReps)110 public abstract void runTest(Object context, int numReps); cleanupTest(TestEnvironment env, Object context)111 public abstract void cleanupTest(TestEnvironment env, Object context); 112 runTestLoop(TestEnvironment env, Result result, Object ctx)113 public void runTestLoop(TestEnvironment env, Result result, Object ctx) { 114 // Prime the pump 115 runTest(ctx, 1); 116 117 // Determine the number of reps 118 int numReps = env.getRepCount(); 119 if (numReps == 0) { 120 numReps = calibrate(env, ctx); 121 } 122 result.setReps(numReps); 123 124 int numRuns = env.getRunCount(); 125 for (int i = 0; i < numRuns; i++) { 126 if (env.idle()) { 127 break; 128 } 129 130 env.sync(); 131 env.startTiming(); 132 runTest(ctx, numReps); 133 env.sync(); 134 env.stopTiming(); 135 result.addTime(env.getTimeMillis()); 136 137 env.flushToScreen(); 138 } 139 } 140 calibrate(TestEnvironment env, Object ctx)141 public int calibrate(TestEnvironment env, Object ctx) { 142 long testTime = env.getTestTime(); 143 int numReps = 0; 144 int totalReps = 0; 145 146 // First do one at a time until we get to 1 second elapsed 147 // But, if we get to 1000 reps we'll start ramping up our 148 // reps per cycle and throwing sync() calls in to make sure 149 // we aren't spinning our gears queueing up graphics calls 150 env.idle(); 151 long now = System.currentTimeMillis(); 152 long startTime = now; 153 while (numReps < 1000 && now < startTime + 1000) { 154 runTest(ctx, 1); 155 numReps++; 156 now = System.currentTimeMillis(); 157 } 158 159 // Time to shift gears into an exponential number of tests 160 // sync() each time in case batching at a lower level is 161 // causing us to spin our gears 162 env.sync(); 163 now = System.currentTimeMillis(); 164 int reps = 250; 165 while (now < startTime + 1000) { 166 runTest(ctx, reps); 167 env.sync(); 168 numReps += reps; 169 reps *= 2; 170 now = System.currentTimeMillis(); 171 } 172 173 // Now keep estimating how many reps it takes to hit our target 174 // time exactly, trying it out, and guessing again. 175 while (now < startTime + testTime) { 176 int estimate = (int) (numReps * testTime / (now - startTime)); 177 if (estimate <= numReps) { 178 estimate = numReps+1; 179 } 180 runTest(ctx, estimate - numReps); 181 numReps = estimate; 182 env.sync(); 183 now = System.currentTimeMillis(); 184 } 185 186 // Now make one last estimate of how many reps it takes to 187 // hit the target exactly in case we overshot. 188 int estimate = (int) (numReps * testTime / (now - startTime)); 189 if (estimate < 1) { 190 estimate = 1; 191 } 192 return estimate; 193 } 194 195 /* 196 * Finds a new width (w2) such that 197 * (w-2) <= w2 <= w 198 * and w2 is not a multiple of 3 (the X step size) 199 * and GCD(w2, h) is as small as possible 200 */ 201 static int prevw; adjustWidth(int w, int h)202 public static int adjustWidth(int w, int h) { 203 int bestv = w; 204 int bestw = w; 205 boolean verbose = (prevw != w && J2DBench.verbose.isEnabled()); 206 for (int i = 0; i < 3; i++) { 207 int w2 = w-i; 208 int u = w2; 209 int v = h; 210 while (u > 0) { 211 if (u < v) { int t = u; u = v; v = t; } 212 u -= v; 213 } 214 if (verbose) { 215 System.out.println("w = "+w2+", h = "+h+ 216 ", w % 3 == "+(w2 % 3)+ 217 ", gcd(w, h) = "+v); 218 } 219 if (v < bestv && (w2 % 3) != 0) { 220 bestv = v; 221 bestw = w2; 222 } 223 } 224 if (verbose) { 225 System.out.println("using "+bestw+" (gcd = "+bestv+")"); 226 prevw = w; 227 } 228 return bestw; 229 } 230 toString()231 public String toString() { 232 return "Test("+getTreeName()+")"; 233 } 234 235 public static class DependentLink { add(DependentLink d, Modifier mod, Modifier.Filter filter)236 public static DependentLink add(DependentLink d, Modifier mod, 237 Modifier.Filter filter) 238 { 239 DependentLink dl = new DependentLink(mod, filter); 240 if (d == null) { 241 d = dl; 242 } else { 243 DependentLink last = d; 244 while (last.next != null) { 245 last = last.next; 246 } 247 last.next = dl; 248 } 249 return d; 250 } 251 252 private DependentLink next; 253 private Modifier mod; 254 private Modifier.Filter filter; 255 DependentLink(Modifier mod, Modifier.Filter filter)256 private DependentLink(Modifier mod, Modifier.Filter filter) { 257 this.mod = mod; 258 this.filter = filter; 259 } 260 getModifier()261 public Modifier getModifier() { 262 return mod; 263 } 264 getFilter()265 public Modifier.Filter getFilter() { 266 return filter; 267 } 268 getNext()269 public DependentLink getNext() { 270 return next; 271 } 272 recurseAndRun(TestEnvironment env, Test test)273 public void recurseAndRun(TestEnvironment env, Test test) { 274 Modifier.Iterator iter = mod.getIterator(env); 275 while (iter.hasNext()) { 276 Object val = iter.next(); 277 if (filter == null || filter.isCompatible(val)) { 278 mod.modifyTest(env, val); 279 if (next == null) { 280 test.runOneTest(env); 281 env.idle(); // One more time outside of runOneTest() 282 } else { 283 next.recurseAndRun(env, test); 284 } 285 mod.restoreTest(env, val); 286 } 287 } 288 } 289 } 290 } 291