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