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 import java.util.Vector; 44 import java.util.Hashtable; 45 import java.util.Enumeration; 46 import java.io.PrintWriter; 47 import java.util.HashMap; 48 49 public class Result { 50 public static final int RATE_UNKNOWN = 0; 51 52 public static final int WORK_OPS = 1; 53 public static final int WORK_UNITS = 2; 54 public static final int WORK_THOUSANDS = 4; 55 public static final int WORK_MILLIONS = 6; 56 public static final int WORK_AUTO = 8; 57 58 public static final int TIME_SECONDS = 10; 59 public static final int TIME_MILLIS = 11; 60 public static final int TIME_MICROS = 12; 61 public static final int TIME_NANOS = 13; 62 public static final int TIME_AUTO = 14; 63 64 static Group resultoptroot; 65 static Option.ObjectChoice timeOpt; 66 static Option.ObjectChoice workOpt; 67 static Option.ObjectChoice rateOpt; 68 init()69 public static void init() { 70 resultoptroot = new Group(TestEnvironment.globaloptroot, 71 "results", "Result Options"); 72 73 String workStrings[] = { 74 "units", 75 "kilounits", 76 "megaunits", 77 "autounits", 78 "ops", 79 "kiloops", 80 "megaops", 81 "autoops", 82 }; 83 String workDescriptions[] = { 84 "Test Units", 85 "Thousands of Test Units", 86 "Millions of Test Units", 87 "Auto-scaled Test Units", 88 "Operations", 89 "Thousands of Operations", 90 "Millions of Operations", 91 "Auto-scaled Operations", 92 }; 93 Integer workObjects[] = { 94 new Integer(WORK_UNITS), 95 new Integer(WORK_THOUSANDS), 96 new Integer(WORK_MILLIONS), 97 new Integer(WORK_AUTO), 98 new Integer(WORK_OPS | WORK_UNITS), 99 new Integer(WORK_OPS | WORK_THOUSANDS), 100 new Integer(WORK_OPS | WORK_MILLIONS), 101 new Integer(WORK_OPS | WORK_AUTO), 102 }; 103 workOpt = new Option.ObjectChoice(resultoptroot, 104 "workunits", "Work Units", 105 workStrings, workObjects, 106 workStrings, workDescriptions, 107 0); 108 String timeStrings[] = { 109 "sec", 110 "msec", 111 "usec", 112 "nsec", 113 "autosec", 114 }; 115 String timeDescriptions[] = { 116 "Seconds", 117 "Milliseconds", 118 "Microseconds", 119 "Nanoseconds", 120 "Auto-scaled seconds", 121 }; 122 Integer timeObjects[] = { 123 new Integer(TIME_SECONDS), 124 new Integer(TIME_MILLIS), 125 new Integer(TIME_MICROS), 126 new Integer(TIME_NANOS), 127 new Integer(TIME_AUTO), 128 }; 129 timeOpt = new Option.ObjectChoice(resultoptroot, 130 "timeunits", "Time Units", 131 timeStrings, timeObjects, 132 timeStrings, timeDescriptions, 133 0); 134 String rateStrings[] = { 135 "unitspersec", 136 "secsperunit", 137 }; 138 String rateDescriptions[] = { 139 "Work units per Time", 140 "Time units per Work", 141 }; 142 Boolean rateObjects[] = { 143 Boolean.FALSE, 144 Boolean.TRUE, 145 }; 146 rateOpt = new Option.ObjectChoice(resultoptroot, 147 "ratio", "Rate Ratio", 148 rateStrings, rateObjects, 149 rateStrings, rateDescriptions, 150 0); 151 } 152 isTimeUnit(int unit)153 public static boolean isTimeUnit(int unit) { 154 return (unit >= TIME_SECONDS && unit <= TIME_AUTO); 155 } 156 isWorkUnit(int unit)157 public static boolean isWorkUnit(int unit) { 158 return (unit >= WORK_OPS && unit <= (WORK_AUTO | WORK_OPS)); 159 } 160 parseRateOpt(String opt)161 public static String parseRateOpt(String opt) { 162 int timeScale = timeOpt.getIntValue(); 163 int workScale = workOpt.getIntValue(); 164 boolean invertRate = rateOpt.getBooleanValue(); 165 int divindex = opt.indexOf('/'); 166 if (divindex < 0) { 167 int unit = parseUnit(opt); 168 if (isTimeUnit(unit)) { 169 timeScale = unit; 170 } else if (isWorkUnit(unit)) { 171 workScale = unit; 172 } else { 173 return "Bad unit: "+opt; 174 } 175 } else { 176 int unit1 = parseUnit(opt.substring(0,divindex)); 177 int unit2 = parseUnit(opt.substring(divindex+1)); 178 if (isTimeUnit(unit1)) { 179 if (isWorkUnit(unit2)) { 180 timeScale = unit1; 181 workScale = unit2; 182 invertRate = true; 183 } else if (isTimeUnit(unit2)) { 184 return "Both time units: "+opt; 185 } else { 186 return "Bad denominator: "+opt; 187 } 188 } else if (isWorkUnit(unit1)) { 189 if (isWorkUnit(unit2)) { 190 return "Both work units: "+opt; 191 } else if (isTimeUnit(unit2)) { 192 timeScale = unit2; 193 workScale = unit1; 194 invertRate = false; 195 } else { 196 return "Bad denominator: "+opt; 197 } 198 } else { 199 return "Bad numerator: "+opt; 200 } 201 } 202 timeOpt.setValue(timeScale); 203 workOpt.setValue(workScale); 204 rateOpt.setValue(invertRate); 205 return null; 206 } 207 208 private static HashMap unitMap; 209 210 static { 211 unitMap = new HashMap(); 212 unitMap.put("U", new Integer(WORK_UNITS)); 213 unitMap.put("M", new Integer(WORK_MILLIONS)); 214 unitMap.put("K", new Integer(WORK_THOUSANDS)); 215 unitMap.put("A", new Integer(WORK_AUTO)); 216 unitMap.put("MU", new Integer(WORK_MILLIONS)); 217 unitMap.put("KU", new Integer(WORK_THOUSANDS)); 218 unitMap.put("AU", new Integer(WORK_AUTO)); 219 220 unitMap.put("O", new Integer(WORK_UNITS | WORK_OPS)); 221 unitMap.put("NO", new Integer(WORK_UNITS | WORK_OPS)); 222 unitMap.put("MO", new Integer(WORK_MILLIONS | WORK_OPS)); 223 unitMap.put("KO", new Integer(WORK_THOUSANDS | WORK_OPS)); 224 unitMap.put("AO", new Integer(WORK_AUTO | WORK_OPS)); 225 226 unitMap.put("s", new Integer(TIME_SECONDS)); 227 unitMap.put("m", new Integer(TIME_MILLIS)); 228 unitMap.put("u", new Integer(TIME_MICROS)); 229 unitMap.put("n", new Integer(TIME_NANOS)); 230 unitMap.put("a", new Integer(TIME_AUTO)); 231 } 232 parseUnit(String c)233 public static int parseUnit(String c) { 234 Integer u = (Integer) unitMap.get(c); 235 if (u != null) { 236 return u.intValue(); 237 } 238 return RATE_UNKNOWN; 239 } 240 241 String unitname = "unit"; 242 Test test; 243 int repsPerRun; 244 int unitsPerRep; 245 Vector times; 246 Hashtable modifiers; 247 Throwable error; 248 Result(Test test)249 public Result(Test test) { 250 this.test = test; 251 this.repsPerRun = 1; 252 this.unitsPerRep = 1; 253 times = new Vector(); 254 } 255 setReps(int reps)256 public void setReps(int reps) { 257 this.repsPerRun = reps; 258 } 259 setUnits(int units)260 public void setUnits(int units) { 261 this.unitsPerRep = units; 262 } 263 setUnitName(String name)264 public void setUnitName(String name) { 265 this.unitname = name; 266 } 267 addTime(long time)268 public void addTime(long time) { 269 if (J2DBench.printresults.isEnabled()) { 270 System.out.println(test+" took "+time+"ms for "+ 271 getRepsPerRun()+" reps"); 272 } 273 times.addElement(new Long(time)); 274 } 275 setError(Throwable t)276 public void setError(Throwable t) { 277 this.error = t; 278 } 279 setModifiers(Hashtable modifiers)280 public void setModifiers(Hashtable modifiers) { 281 this.modifiers = modifiers; 282 } 283 getError()284 public Throwable getError() { 285 return error; 286 } 287 getRepsPerRun()288 public int getRepsPerRun() { 289 return repsPerRun; 290 } 291 getUnitsPerRep()292 public int getUnitsPerRep() { 293 return unitsPerRep; 294 } 295 getUnitsPerRun()296 public long getUnitsPerRun() { 297 return ((long) getRepsPerRun()) * ((long) getUnitsPerRep()); 298 } 299 getModifiers()300 public Hashtable getModifiers() { 301 return modifiers; 302 } 303 getNumRuns()304 public long getNumRuns() { 305 return times.size(); 306 } 307 getTime(int index)308 public long getTime(int index) { 309 return ((Long) times.elementAt(index)).longValue(); 310 } 311 getRepsPerSecond(int index)312 public double getRepsPerSecond(int index) { 313 return (getRepsPerRun() * 1000.0) / getTime(index); 314 } 315 getUnitsPerSecond(int index)316 public double getUnitsPerSecond(int index) { 317 return (getUnitsPerRun() * 1000.0) / getTime(index); 318 } 319 getTotalReps()320 public long getTotalReps() { 321 return getRepsPerRun() * getNumRuns(); 322 } 323 getTotalUnits()324 public long getTotalUnits() { 325 return getUnitsPerRun() * getNumRuns(); 326 } 327 getTotalTime()328 public long getTotalTime() { 329 long totalTime = 0; 330 for (int i = 0; i < times.size(); i++) { 331 totalTime += getTime(i); 332 } 333 return totalTime; 334 } 335 getAverageRepsPerSecond()336 public double getAverageRepsPerSecond() { 337 return (getTotalReps() * 1000.0) / getTotalTime(); 338 } 339 getAverageUnitsPerSecond()340 public double getAverageUnitsPerSecond() { 341 return (getTotalUnits() * 1000.0) / getTotalTime(); 342 } 343 getAverageString()344 public String getAverageString() { 345 int timeScale = timeOpt.getIntValue(); 346 int workScale = workOpt.getIntValue(); 347 boolean invertRate = rateOpt.getBooleanValue(); 348 double time = getTotalTime(); 349 String timeprefix = ""; 350 switch (timeScale) { 351 case TIME_AUTO: 352 case TIME_SECONDS: 353 time /= 1000; 354 break; 355 case TIME_MILLIS: 356 timeprefix = "m"; 357 break; 358 case TIME_MICROS: 359 time *= 1000.0; 360 timeprefix = "u"; 361 break; 362 case TIME_NANOS: 363 time *= 1000000.0; 364 timeprefix = "n"; 365 break; 366 } 367 368 String workprefix = ""; 369 boolean isOps = (workScale & WORK_OPS) != 0; 370 String workname = isOps ? "op" : unitname; 371 double work = isOps ? getTotalReps() : getTotalUnits(); 372 switch (workScale & (~WORK_OPS)) { 373 case WORK_AUTO: 374 case WORK_UNITS: 375 break; 376 case WORK_THOUSANDS: 377 work /= 1000.0; 378 workprefix = "K"; 379 break; 380 case WORK_MILLIONS: 381 work /= 1000000.0; 382 workprefix = "M"; 383 break; 384 } 385 if (invertRate) { 386 double rate = time / work; 387 if (timeScale == TIME_AUTO) { 388 if (rate < 1.0) { 389 rate *= 1000.0; 390 timeprefix = "m"; 391 if (rate < 1.0) { 392 rate *= 1000.0; 393 timeprefix = "u"; 394 if (rate < 1.0) { 395 rate *= 1000.0; 396 timeprefix = "n"; 397 } 398 } 399 } 400 } 401 return rate+" "+timeprefix+"secs/"+workprefix+workname; 402 } else { 403 double rate = work / time; 404 if (workScale == WORK_AUTO) { 405 if (rate > 1000.0) { 406 rate /= 1000.0; 407 workprefix = "K"; 408 if (rate > 1000.0) { 409 rate /= 1000.0; 410 workprefix = "M"; 411 } 412 } 413 } 414 return rate+" "+workprefix+workname+"s/"+timeprefix+"sec"; 415 } 416 } 417 summarize()418 public void summarize() { 419 if (error != null) { 420 System.out.println(test+" skipped due to "+error); 421 error.printStackTrace(System.out); 422 } else { 423 System.out.println(test+" averaged "+getAverageString()); 424 } 425 if (true) { 426 Enumeration enum_ = modifiers.keys(); 427 System.out.print(" with"); 428 String sep = " "; 429 while (enum_.hasMoreElements()) { 430 Modifier mod = (Modifier) enum_.nextElement(); 431 Object v = modifiers.get(mod); 432 System.out.print(sep); 433 System.out.print(mod.getAbbreviatedModifierDescription(v)); 434 sep = ", "; 435 } 436 System.out.println(); 437 } 438 } 439 write(PrintWriter pw)440 public void write(PrintWriter pw) { 441 pw.println(" <result "+ 442 "num-reps=\""+getRepsPerRun()+"\" "+ 443 "num-units=\""+getUnitsPerRep()+"\" "+ 444 "name=\""+test.getTreeName()+"\">"); 445 Enumeration enum_ = modifiers.keys(); 446 while (enum_.hasMoreElements()) { 447 Modifier mod = (Modifier) enum_.nextElement(); 448 Object v = modifiers.get(mod); 449 String val = mod.getModifierValueName(v); 450 pw.println(" <option "+ 451 "key=\""+mod.getTreeName()+"\" "+ 452 "value=\""+val+"\"/>"); 453 } 454 for (int i = 0; i < getNumRuns(); i++) { 455 pw.println(" <time value=\""+getTime(i)+"\"/>"); 456 } 457 pw.println(" </result>"); 458 } 459 } 460