| /* |
| * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * This source code is provided to illustrate the usage of a given feature |
| * or technique and has been deliberately simplified. Additional steps |
| * required for a production-quality application, such as security checks, |
| * input validation and proper error handling, might not be present in |
| * this sample code. |
| */ |
| |
| |
| package j2dbench; |
| |
| import java.util.Vector; |
| import java.util.Hashtable; |
| import java.util.Enumeration; |
| import java.io.PrintWriter; |
| import java.util.HashMap; |
| |
| public class Result { |
| public static final int RATE_UNKNOWN = 0; |
| |
| public static final int WORK_OPS = 1; |
| public static final int WORK_UNITS = 2; |
| public static final int WORK_THOUSANDS = 4; |
| public static final int WORK_MILLIONS = 6; |
| public static final int WORK_AUTO = 8; |
| |
| public static final int TIME_SECONDS = 10; |
| public static final int TIME_MILLIS = 11; |
| public static final int TIME_MICROS = 12; |
| public static final int TIME_NANOS = 13; |
| public static final int TIME_AUTO = 14; |
| |
| static Group resultoptroot; |
| static Option.ObjectChoice timeOpt; |
| static Option.ObjectChoice workOpt; |
| static Option.ObjectChoice rateOpt; |
| |
| public static void init() { |
| resultoptroot = new Group(TestEnvironment.globaloptroot, |
| "results", "Result Options"); |
| |
| String workStrings[] = { |
| "units", |
| "kilounits", |
| "megaunits", |
| "autounits", |
| "ops", |
| "kiloops", |
| "megaops", |
| "autoops", |
| }; |
| String workDescriptions[] = { |
| "Test Units", |
| "Thousands of Test Units", |
| "Millions of Test Units", |
| "Auto-scaled Test Units", |
| "Operations", |
| "Thousands of Operations", |
| "Millions of Operations", |
| "Auto-scaled Operations", |
| }; |
| Integer workObjects[] = { |
| new Integer(WORK_UNITS), |
| new Integer(WORK_THOUSANDS), |
| new Integer(WORK_MILLIONS), |
| new Integer(WORK_AUTO), |
| new Integer(WORK_OPS | WORK_UNITS), |
| new Integer(WORK_OPS | WORK_THOUSANDS), |
| new Integer(WORK_OPS | WORK_MILLIONS), |
| new Integer(WORK_OPS | WORK_AUTO), |
| }; |
| workOpt = new Option.ObjectChoice(resultoptroot, |
| "workunits", "Work Units", |
| workStrings, workObjects, |
| workStrings, workDescriptions, |
| 0); |
| String timeStrings[] = { |
| "sec", |
| "msec", |
| "usec", |
| "nsec", |
| "autosec", |
| }; |
| String timeDescriptions[] = { |
| "Seconds", |
| "Milliseconds", |
| "Microseconds", |
| "Nanoseconds", |
| "Auto-scaled seconds", |
| }; |
| Integer timeObjects[] = { |
| new Integer(TIME_SECONDS), |
| new Integer(TIME_MILLIS), |
| new Integer(TIME_MICROS), |
| new Integer(TIME_NANOS), |
| new Integer(TIME_AUTO), |
| }; |
| timeOpt = new Option.ObjectChoice(resultoptroot, |
| "timeunits", "Time Units", |
| timeStrings, timeObjects, |
| timeStrings, timeDescriptions, |
| 0); |
| String rateStrings[] = { |
| "unitspersec", |
| "secsperunit", |
| }; |
| String rateDescriptions[] = { |
| "Work units per Time", |
| "Time units per Work", |
| }; |
| Boolean rateObjects[] = { |
| Boolean.FALSE, |
| Boolean.TRUE, |
| }; |
| rateOpt = new Option.ObjectChoice(resultoptroot, |
| "ratio", "Rate Ratio", |
| rateStrings, rateObjects, |
| rateStrings, rateDescriptions, |
| 0); |
| } |
| |
| public static boolean isTimeUnit(int unit) { |
| return (unit >= TIME_SECONDS && unit <= TIME_AUTO); |
| } |
| |
| public static boolean isWorkUnit(int unit) { |
| return (unit >= WORK_OPS && unit <= (WORK_AUTO | WORK_OPS)); |
| } |
| |
| public static String parseRateOpt(String opt) { |
| int timeScale = timeOpt.getIntValue(); |
| int workScale = workOpt.getIntValue(); |
| boolean invertRate = rateOpt.getBooleanValue(); |
| int divindex = opt.indexOf('/'); |
| if (divindex < 0) { |
| int unit = parseUnit(opt); |
| if (isTimeUnit(unit)) { |
| timeScale = unit; |
| } else if (isWorkUnit(unit)) { |
| workScale = unit; |
| } else { |
| return "Bad unit: "+opt; |
| } |
| } else { |
| int unit1 = parseUnit(opt.substring(0,divindex)); |
| int unit2 = parseUnit(opt.substring(divindex+1)); |
| if (isTimeUnit(unit1)) { |
| if (isWorkUnit(unit2)) { |
| timeScale = unit1; |
| workScale = unit2; |
| invertRate = true; |
| } else if (isTimeUnit(unit2)) { |
| return "Both time units: "+opt; |
| } else { |
| return "Bad denominator: "+opt; |
| } |
| } else if (isWorkUnit(unit1)) { |
| if (isWorkUnit(unit2)) { |
| return "Both work units: "+opt; |
| } else if (isTimeUnit(unit2)) { |
| timeScale = unit2; |
| workScale = unit1; |
| invertRate = false; |
| } else { |
| return "Bad denominator: "+opt; |
| } |
| } else { |
| return "Bad numerator: "+opt; |
| } |
| } |
| timeOpt.setValue(timeScale); |
| workOpt.setValue(workScale); |
| rateOpt.setValue(invertRate); |
| return null; |
| } |
| |
| private static HashMap unitMap; |
| |
| static { |
| unitMap = new HashMap(); |
| unitMap.put("U", new Integer(WORK_UNITS)); |
| unitMap.put("M", new Integer(WORK_MILLIONS)); |
| unitMap.put("K", new Integer(WORK_THOUSANDS)); |
| unitMap.put("A", new Integer(WORK_AUTO)); |
| unitMap.put("MU", new Integer(WORK_MILLIONS)); |
| unitMap.put("KU", new Integer(WORK_THOUSANDS)); |
| unitMap.put("AU", new Integer(WORK_AUTO)); |
| |
| unitMap.put("O", new Integer(WORK_UNITS | WORK_OPS)); |
| unitMap.put("NO", new Integer(WORK_UNITS | WORK_OPS)); |
| unitMap.put("MO", new Integer(WORK_MILLIONS | WORK_OPS)); |
| unitMap.put("KO", new Integer(WORK_THOUSANDS | WORK_OPS)); |
| unitMap.put("AO", new Integer(WORK_AUTO | WORK_OPS)); |
| |
| unitMap.put("s", new Integer(TIME_SECONDS)); |
| unitMap.put("m", new Integer(TIME_MILLIS)); |
| unitMap.put("u", new Integer(TIME_MICROS)); |
| unitMap.put("n", new Integer(TIME_NANOS)); |
| unitMap.put("a", new Integer(TIME_AUTO)); |
| } |
| |
| public static int parseUnit(String c) { |
| Integer u = (Integer) unitMap.get(c); |
| if (u != null) { |
| return u.intValue(); |
| } |
| return RATE_UNKNOWN; |
| } |
| |
| String unitname = "unit"; |
| Test test; |
| int repsPerRun; |
| int unitsPerRep; |
| Vector times; |
| Hashtable modifiers; |
| Throwable error; |
| |
| public Result(Test test) { |
| this.test = test; |
| this.repsPerRun = 1; |
| this.unitsPerRep = 1; |
| times = new Vector(); |
| } |
| |
| public void setReps(int reps) { |
| this.repsPerRun = reps; |
| } |
| |
| public void setUnits(int units) { |
| this.unitsPerRep = units; |
| } |
| |
| public void setUnitName(String name) { |
| this.unitname = name; |
| } |
| |
| public void addTime(long time) { |
| if (J2DBench.printresults.isEnabled()) { |
| System.out.println(test+" took "+time+"ms for "+ |
| getRepsPerRun()+" reps"); |
| } |
| times.addElement(new Long(time)); |
| } |
| |
| public void setError(Throwable t) { |
| this.error = t; |
| } |
| |
| public void setModifiers(Hashtable modifiers) { |
| this.modifiers = modifiers; |
| } |
| |
| public Throwable getError() { |
| return error; |
| } |
| |
| public int getRepsPerRun() { |
| return repsPerRun; |
| } |
| |
| public int getUnitsPerRep() { |
| return unitsPerRep; |
| } |
| |
| public long getUnitsPerRun() { |
| return ((long) getRepsPerRun()) * ((long) getUnitsPerRep()); |
| } |
| |
| public Hashtable getModifiers() { |
| return modifiers; |
| } |
| |
| public long getNumRuns() { |
| return times.size(); |
| } |
| |
| public long getTime(int index) { |
| return ((Long) times.elementAt(index)).longValue(); |
| } |
| |
| public double getRepsPerSecond(int index) { |
| return (getRepsPerRun() * 1000.0) / getTime(index); |
| } |
| |
| public double getUnitsPerSecond(int index) { |
| return (getUnitsPerRun() * 1000.0) / getTime(index); |
| } |
| |
| public long getTotalReps() { |
| return getRepsPerRun() * getNumRuns(); |
| } |
| |
| public long getTotalUnits() { |
| return getUnitsPerRun() * getNumRuns(); |
| } |
| |
| public long getTotalTime() { |
| long totalTime = 0; |
| for (int i = 0; i < times.size(); i++) { |
| totalTime += getTime(i); |
| } |
| return totalTime; |
| } |
| |
| public double getAverageRepsPerSecond() { |
| return (getTotalReps() * 1000.0) / getTotalTime(); |
| } |
| |
| public double getAverageUnitsPerSecond() { |
| return (getTotalUnits() * 1000.0) / getTotalTime(); |
| } |
| |
| public String getAverageString() { |
| int timeScale = timeOpt.getIntValue(); |
| int workScale = workOpt.getIntValue(); |
| boolean invertRate = rateOpt.getBooleanValue(); |
| double time = getTotalTime(); |
| String timeprefix = ""; |
| switch (timeScale) { |
| case TIME_AUTO: |
| case TIME_SECONDS: |
| time /= 1000; |
| break; |
| case TIME_MILLIS: |
| timeprefix = "m"; |
| break; |
| case TIME_MICROS: |
| time *= 1000.0; |
| timeprefix = "u"; |
| break; |
| case TIME_NANOS: |
| time *= 1000000.0; |
| timeprefix = "n"; |
| break; |
| } |
| |
| String workprefix = ""; |
| boolean isOps = (workScale & WORK_OPS) != 0; |
| String workname = isOps ? "op" : unitname; |
| double work = isOps ? getTotalReps() : getTotalUnits(); |
| switch (workScale & (~WORK_OPS)) { |
| case WORK_AUTO: |
| case WORK_UNITS: |
| break; |
| case WORK_THOUSANDS: |
| work /= 1000.0; |
| workprefix = "K"; |
| break; |
| case WORK_MILLIONS: |
| work /= 1000000.0; |
| workprefix = "M"; |
| break; |
| } |
| if (invertRate) { |
| double rate = time / work; |
| if (timeScale == TIME_AUTO) { |
| if (rate < 1.0) { |
| rate *= 1000.0; |
| timeprefix = "m"; |
| if (rate < 1.0) { |
| rate *= 1000.0; |
| timeprefix = "u"; |
| if (rate < 1.0) { |
| rate *= 1000.0; |
| timeprefix = "n"; |
| } |
| } |
| } |
| } |
| return rate+" "+timeprefix+"secs/"+workprefix+workname; |
| } else { |
| double rate = work / time; |
| if (workScale == WORK_AUTO) { |
| if (rate > 1000.0) { |
| rate /= 1000.0; |
| workprefix = "K"; |
| if (rate > 1000.0) { |
| rate /= 1000.0; |
| workprefix = "M"; |
| } |
| } |
| } |
| return rate+" "+workprefix+workname+"s/"+timeprefix+"sec"; |
| } |
| } |
| |
| public void summarize() { |
| if (error != null) { |
| System.out.println(test+" skipped due to "+error); |
| error.printStackTrace(System.out); |
| } else { |
| System.out.println(test+" averaged "+getAverageString()); |
| } |
| if (true) { |
| Enumeration enum_ = modifiers.keys(); |
| System.out.print(" with"); |
| String sep = " "; |
| while (enum_.hasMoreElements()) { |
| Modifier mod = (Modifier) enum_.nextElement(); |
| Object v = modifiers.get(mod); |
| System.out.print(sep); |
| System.out.print(mod.getAbbreviatedModifierDescription(v)); |
| sep = ", "; |
| } |
| System.out.println(); |
| } |
| } |
| |
| public void write(PrintWriter pw) { |
| pw.println(" <result "+ |
| "num-reps=\""+getRepsPerRun()+"\" "+ |
| "num-units=\""+getUnitsPerRep()+"\" "+ |
| "name=\""+test.getTreeName()+"\">"); |
| Enumeration enum_ = modifiers.keys(); |
| while (enum_.hasMoreElements()) { |
| Modifier mod = (Modifier) enum_.nextElement(); |
| Object v = modifiers.get(mod); |
| String val = mod.getModifierValueName(v); |
| pw.println(" <option "+ |
| "key=\""+mod.getTreeName()+"\" "+ |
| "value=\""+val+"\"/>"); |
| } |
| for (int i = 0; i < getNumRuns(); i++) { |
| pw.println(" <time value=\""+getTime(i)+"\"/>"); |
| } |
| pw.println(" </result>"); |
| } |
| } |