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