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.report;
  33 
  34 import java.util.Vector;
  35 import java.util.Hashtable;
  36 import java.util.Enumeration;
  37 import java.io.BufferedReader;
  38 import java.io.FileReader;
  39 import java.io.IOException;
  40 import java.io.PrintStream;
  41 
  42 public class J2DAnalyzer {
  43     static Vector results = new Vector();
  44     static GroupResultSetHolder groupHolder;
  45 
  46     static final int BEST = 1;    /* The best score */
  47     static final int WORST = 2;   /* The worst score */
  48     static final int AVERAGE = 3; /* Average of all scores */
  49     static final int MIDAVG = 4;  /* Average of all but the best and worst */
  50 
  51     static int mode = MIDAVG;
  52 
  53     public static void usage(PrintStream out) {
  54         out.println("usage:");
  55         out.println("    java -jar J2DAnalyzer.jar [Option]*");
  56         out.println();
  57         out.println("where options are any of the following in any order:");
  58         out.println("   -Help|-Usage          "+
  59                     "print out this usage statement");
  60         out.println("   -Group:<groupname>    "+
  61                     "the following result sets are combined into a group");
  62         out.println("   -NoGroup              "+
  63                     "the following result sets stand on their own");
  64         out.println("   -ShowUncontested      "+
  65                     "show results even when only result set has a result");
  66         out.println("   -Graph                "+
  67                     "graph the results visually (using lines of *'s)");
  68         out.println("   -Best                 "+
  69                     "use best time within a resultset");
  70         out.println("   -Worst                "+
  71                     "use worst time within a resultset");
  72         out.println("   -Average|-Avg         "+
  73                     "use average of all times within a resultset");
  74         out.println("   -MidAverage|-MidAvg   "+
  75                     "like -Average but ignore best and worst times");
  76         out.println("   <resultfilename>      "+
  77                     "load in results from named file");
  78         out.println();
  79         out.println("results within a result set "+
  80                     "use Best/Worst/Average mode");
  81         out.println("results within a group "+
  82                     "are best of all result sets in that group");
  83     }
  84 
  85     public static void main(String argv[]) {
  86         boolean gavehelp = false;
  87         boolean graph = false;
  88         boolean ignoreuncontested = true;
  89         if (argv.length > 0 && argv[0].equalsIgnoreCase("-html")) {
  90             String newargs[] = new String[argv.length-1];
  91             System.arraycopy(argv, 1, newargs, 0, newargs.length);
  92             HTMLSeriesReporter.main(newargs);
  93             return;
  94         }
  95         for (int i = 0; i < argv.length; i++) {
  96             String arg = argv[i];
  97             if (arg.regionMatches(true, 0, "-Group:", 0, 7)) {
  98                 groupHolder = new GroupResultSetHolder();
  99                 groupHolder.setTitle(arg.substring(7));
 100                 results.add(groupHolder);
 101             } else if (arg.equalsIgnoreCase("-NoGroup")) {
 102                 groupHolder = null;
 103             } else if (arg.equalsIgnoreCase("-ShowUncontested")) {
 104                 ignoreuncontested = false;
 105             } else if (arg.equalsIgnoreCase("-Graph")) {
 106                 graph = true;
 107             } else if (arg.equalsIgnoreCase("-Best")) {
 108                 mode = BEST;
 109             } else if (arg.equalsIgnoreCase("-Worst")) {
 110                 mode = WORST;
 111             } else if (arg.equalsIgnoreCase("-Average") ||
 112                        arg.equalsIgnoreCase("-Avg"))
 113             {
 114                 mode = AVERAGE;
 115             } else if (arg.equalsIgnoreCase("-MidAverage") ||
 116                        arg.equalsIgnoreCase("-MidAvg"))
 117             {
 118                 mode = MIDAVG;
 119             } else if (arg.equalsIgnoreCase("-Help") ||
 120                        arg.equalsIgnoreCase("-Usage"))
 121             {
 122                 usage(System.out);
 123                 gavehelp = true;
 124             } else {
 125                 readResults(argv[i]);
 126             }
 127         }
 128 
 129         if (results.size() == 0) {
 130             if (!gavehelp) {
 131                 System.err.println("No results loaded");
 132                 usage(System.err);
 133             }
 134             return;
 135         }
 136 
 137         int numsets = results.size();
 138         double totalscore[] = new double[numsets];
 139         int numwins[] = new int[numsets];
 140         int numties[] = new int[numsets];
 141         int numloss[] = new int[numsets];
 142         int numtests[] = new int[numsets];
 143         double bestscore[] = new double[numsets];
 144         double worstscore[] = new double[numsets];
 145         double bestspread[] = new double[numsets];
 146         double worstspread[] = new double[numsets];
 147         for (int i = 0; i < numsets; i++) {
 148             bestscore[i] = Double.NEGATIVE_INFINITY;
 149             worstscore[i] = Double.POSITIVE_INFINITY;
 150             bestspread[i] = Double.POSITIVE_INFINITY;
 151             worstspread[i] = Double.NEGATIVE_INFINITY;
 152         }
 153 
 154         ResultSetHolder base = (ResultSetHolder) results.elementAt(0);
 155         Enumeration enum_ = base.getKeyEnumeration();
 156         Vector keyvector = new Vector();
 157         while (enum_.hasMoreElements()) {
 158             keyvector.add(enum_.nextElement());
 159         }
 160         String keys[] = new String[keyvector.size()];
 161         keyvector.copyInto(keys);
 162         sort(keys);
 163         enum_ = ResultHolder.commonkeys.keys();
 164         System.out.println("Options common across all tests:");
 165         if (ResultHolder.commonname != null &&
 166             ResultHolder.commonname.length() != 0)
 167         {
 168             System.out.println("  testname="+ResultHolder.commonname);
 169         }
 170         while (enum_.hasMoreElements()) {
 171             Object key = enum_.nextElement();
 172             System.out.println("  "+key+"="+ResultHolder.commonkeymap.get(key));
 173         }
 174         System.out.println();
 175         for (int k = 0; k < keys.length; k++) {
 176             String key = keys[k];
 177             ResultHolder rh = base.getResultByKey(key);
 178             double score = rh.getScore();
 179             double maxscore = score;
 180             int numcontesting = 0;
 181             for (int i = 0; i < numsets; i++) {
 182                 ResultSetHolder rsh =
 183                     (ResultSetHolder) results.elementAt(i);
 184                 ResultHolder rh2 = rsh.getResultByKey(key);
 185                 if (rh2 != null) {
 186                     if (graph) {
 187                         maxscore = Math.max(maxscore, rh2.getBestScore());
 188                     }
 189                     numcontesting++;
 190                 }
 191             }
 192             if (ignoreuncontested && numcontesting < 2) {
 193                 continue;
 194             }
 195             System.out.println(rh.getShortKey()+":");
 196             for (int i = 0; i < numsets; i++) {
 197                 ResultSetHolder rsh = (ResultSetHolder) results.elementAt(i);
 198                 System.out.print(rsh.getTitle()+": ");
 199                 ResultHolder rh2 = rsh.getResultByKey(key);
 200                 if (rh2 == null) {
 201                     System.out.println("not run");
 202                 } else {
 203                     double score2 = rh2.getScore();
 204                     double percent = calcPercent(score, score2);
 205                     numtests[i]++;
 206                     if (percent < 97.5) {
 207                         numloss[i]++;
 208                     } else if (percent > 102.5) {
 209                         numwins[i]++;
 210                     } else {
 211                         numties[i]++;
 212                     }
 213                     totalscore[i] += score2;
 214                     if (bestscore[i] < percent) {
 215                         bestscore[i] = percent;
 216                     }
 217                     if (worstscore[i] > percent) {
 218                         worstscore[i] = percent;
 219                     }
 220                     double spread = rh2.getSpread();
 221                     if (bestspread[i] > spread) {
 222                         bestspread[i] = spread;
 223                     }
 224                     if (worstspread[i] < spread) {
 225                         worstspread[i] = spread;
 226                     }
 227                     System.out.print(format(score2));
 228                     System.out.print(" (var="+spread+"%)");
 229                     System.out.print(" ("+percent+"%)");
 230                     System.out.println();
 231                     if (graph) {
 232                         int maxlen = 60;
 233                         int avgpos =
 234                             (int) Math.round(maxlen * score / maxscore);
 235                         Vector scores = rh2.getAllScores();
 236                         for (int j = 0; j < scores.size(); j++) {
 237                             double s = ((Double) scores.get(j)).doubleValue();
 238                             int len = (int) Math.round(maxlen * s / maxscore);
 239                             int pos = 0;
 240                             while (pos < len) {
 241                                 System.out.print(pos == avgpos ? '|' : '*');
 242                                 pos++;
 243                             }
 244                             while (pos <= avgpos) {
 245                                 System.out.print(pos == avgpos ? '|' : ' ');
 246                                 pos++;
 247                             }
 248                             System.out.println();
 249                         }
 250                     }
 251                 }
 252             }
 253         }
 254         System.out.println();
 255         System.out.println("Summary:");
 256         for (int i = 0; i < numsets; i++) {
 257             ResultSetHolder rsh = (ResultSetHolder) results.elementAt(i);
 258             System.out.println("  "+rsh.getTitle()+": ");
 259             if (numtests[i] == 0) {
 260                 System.out.println("    No tests matched reference results");
 261             } else {
 262                 double overallscore = totalscore[i]/numtests[i];
 263                 System.out.println("    Number of tests:  "+numtests[i]);
 264                 System.out.println("    Overall average:  "+overallscore);
 265                 System.out.println("    Best spread:      "+bestspread[i]+
 266                                    "% variance");
 267                 System.out.println("    Worst spread:     "+worstspread[i]+
 268                                    "% variance");
 269                 if (i == 0) {
 270                     System.out.println("    (Basis for results comparison)");
 271                 } else {
 272                     System.out.println("    Comparison to basis:");
 273                     System.out.println("      Best result:      "+bestscore[i]+
 274                                        "% of basis");
 275                     System.out.println("      Worst result:     "+worstscore[i]+
 276                                        "% of basis");
 277                     System.out.println("      Number of wins:   "+numwins[i]);
 278                     System.out.println("      Number of ties:   "+numties[i]);
 279                     System.out.println("      Number of losses: "+numloss[i]);
 280                 }
 281             }
 282             System.out.println();
 283         }
 284     }
 285 
 286     public static void readResults(String filename) {
 287         BufferedReader in;
 288         try {
 289             in = new BufferedReader(new FileReader(filename));
 290             readResults(in);
 291         } catch (IOException e) {
 292             System.out.println(e);
 293             return;
 294         }
 295     }
 296 
 297     public static void addResultSet(ResultSetHolder rs) {
 298         if (groupHolder == null) {
 299             results.add(rs);
 300         } else {
 301             groupHolder.addResultSet(rs);
 302         }
 303     }
 304 
 305     public static void readResults(BufferedReader in)
 306         throws IOException
 307     {
 308         String xmlver = in.readLine();
 309         if (xmlver == null || !xmlver.startsWith("<?xml version=\"1.0\"")) {
 310             return;
 311         }
 312         while (true) {
 313             String rsline = in.readLine();
 314             if (rsline == null) {
 315                 break;
 316             }
 317             rsline = rsline.trim();
 318             if (rsline.startsWith("<result-set version=")) {
 319                 String title = getStringAttribute(rsline, "name");
 320                 if (title == null) {
 321                     title = "No title";
 322                 }
 323                 SingleResultSetHolder srs = new SingleResultSetHolder();
 324                 srs.setTitle(title);
 325                 readResultSet(in, srs);
 326                 addResultSet(srs);
 327             }
 328         }
 329     }
 330 
 331     public static void readResultSet(BufferedReader in,
 332                                      SingleResultSetHolder srs)
 333         throws IOException
 334     {
 335         String line;
 336         while ((line = in.readLine()) != null) {
 337             line = line.trim();
 338             if (line.startsWith("<test-desc>")) {
 339                 int index = line.indexOf("<", 11);
 340                 if (index < 0) {
 341                     index = line.length();
 342                 }
 343                 line = line.substring(11, index);
 344                 srs.setDescription(line);
 345             } else if (line.startsWith("<sys-prop")) {
 346                 String key = getStringAttribute(line, "key");
 347                 String val = getStringAttribute(line, "value");
 348                 if (key != null && val != null) {
 349                     srs.setProperty(key, val);
 350                 }
 351             } else if (line.startsWith("<test-date")) {
 352                 srs.setStartTime(getLongAttribute(line, "start"));
 353                 srs.setEndTime(getLongAttribute(line, "end"));
 354             } else if (line.startsWith("<result")) {
 355                 int numreps = getIntAttribute(line, "num-reps");
 356                 int numunits = getIntAttribute(line, "num-units");
 357                 String name = getStringAttribute(line, "name");
 358                 if (numreps > 0 && numunits >= 0 && name != null) {
 359                     ResultHolder rh = new ResultHolder(srs);
 360                     rh.setName(name);
 361                     rh.setReps(numreps);
 362                     rh.setUnits(numunits);
 363                     readResult(in, rh);
 364                     srs.addResult(rh);
 365                 }
 366             } else if (line.equals("</result-set>")) {
 367                 break;
 368             } else {
 369                 System.err.println("Unrecognized line in Result-Set: "+line);
 370             }
 371         }
 372     }
 373 
 374     public static void readResult(BufferedReader in, ResultHolder rh)
 375         throws IOException
 376     {
 377         String line;
 378         while ((line = in.readLine()) != null) {
 379             line = line.trim();
 380             if (line.startsWith("<option")) {
 381                 String key = getStringAttribute(line, "key");
 382                 String val = getStringAttribute(line, "value");
 383                 if (key != null && val != null) {
 384                     rh.addOption(key, val);
 385                 }
 386             } else if (line.startsWith("<time")) {
 387                 long ms = getLongAttribute(line, "value");
 388                 if (ms >= 0) {
 389                     rh.addTime(ms);
 390                 }
 391             } else if (line.equals("</result>")) {
 392                 break;
 393             } else {
 394                 System.err.println("Unrecognized line in Result: "+line);
 395             }
 396         }
 397     }
 398 
 399     public static String getStringAttribute(String line, String attrname) {
 400         int index = line.indexOf(attrname+"=");
 401         if (index < 0) {
 402             return null;
 403         }
 404         index += attrname.length()+1;
 405         int endindex;
 406         if (line.charAt(index) == '\"') {
 407             index++;
 408             endindex = line.indexOf('\"', index);
 409         } else {
 410             endindex = -1;
 411         }
 412         if (endindex < 0) {
 413             endindex = line.indexOf(' ', index);
 414         }
 415         if (endindex < 0) {
 416             endindex = line.indexOf('>', index);
 417         }
 418         if (endindex < 0) {
 419             endindex = line.length();
 420         }
 421         return line.substring(index, endindex);
 422     }
 423 
 424     public static long getLongAttribute(String line, String attrname) {
 425         String val = getStringAttribute(line, attrname);
 426         if (val == null) {
 427             return -1;
 428         }
 429         try {
 430             return Long.parseLong(val);
 431         } catch (NumberFormatException e) {
 432             return -1;
 433         }
 434     }
 435 
 436     public static int getIntAttribute(String line, String attrname) {
 437         String val = getStringAttribute(line, attrname);
 438         if (val == null) {
 439             return -1;
 440         }
 441         try {
 442             return Integer.parseInt(val);
 443         } catch (NumberFormatException e) {
 444             return -1;
 445         }
 446     }
 447 
 448     public abstract static class ResultSetHolder {
 449         private String title;
 450 
 451         public void setTitle(String title) {
 452             this.title = title;
 453         }
 454 
 455         public String getTitle() {
 456             return title;
 457         }
 458 
 459         public abstract Enumeration getKeyEnumeration();
 460 
 461         public abstract Enumeration getResultEnumeration();
 462 
 463         public abstract ResultHolder getResultByKey(String key);
 464     }
 465 
 466     public static class GroupResultSetHolder extends ResultSetHolder {
 467         private Vector members = new Vector();
 468         private Hashtable allresultkeys = new Hashtable();
 469 
 470         public void addResultSet(ResultSetHolder rsh) {
 471             members.add(rsh);
 472             Enumeration enum_ = rsh.getResultEnumeration();
 473             while (enum_.hasMoreElements()) {
 474                 ResultHolder rh = (ResultHolder) enum_.nextElement();
 475                 String key = rh.getKey();
 476                 allresultkeys.put(key, key);
 477             }
 478         }
 479 
 480         private ResultSetHolder getResultSet(int index) {
 481             return (ResultSetHolder) members.elementAt(index);
 482         }
 483 
 484         public Enumeration getKeyEnumeration() {
 485             return allresultkeys.keys();
 486         }
 487 
 488         public Enumeration getResultEnumeration() {
 489             return new Enumerator();
 490         }
 491 
 492         public ResultHolder getResultByKey(String key) {
 493             ResultHolder best = null;
 494             double bestscore = 0.0;
 495             for (int i = 0; i < members.size(); i++) {
 496                 ResultHolder cur = getResultSet(i).getResultByKey(key);
 497                 if (cur != null) {
 498                     double curscore = cur.getScore();
 499                     if (best == null || curscore > bestscore) {
 500                         best = cur;
 501                         bestscore = curscore;
 502                     }
 503                 }
 504             }
 505             return best;
 506         }
 507 
 508         public class Enumerator implements Enumeration {
 509             Enumeration raw = getKeyEnumeration();
 510 
 511             public boolean hasMoreElements() {
 512                 return raw.hasMoreElements();
 513             }
 514 
 515             public Object nextElement() {
 516                 return getResultByKey((String) raw.nextElement());
 517             }
 518         }
 519     }
 520 
 521     public static class SingleResultSetHolder extends ResultSetHolder {
 522         private String desc;
 523         private long start;
 524         private long end;
 525         private Hashtable props = new Hashtable();
 526         private Vector results = new Vector();
 527         private Hashtable resultsbykey = new Hashtable();
 528 
 529         public void setDescription(String desc) {
 530             this.desc = desc;
 531         }
 532 
 533         public String getDescription() {
 534             return desc;
 535         }
 536 
 537         public void setStartTime(long ms) {
 538             start = ms;
 539         }
 540 
 541         public long getStartTime() {
 542             return start;
 543         }
 544 
 545         public void setEndTime(long ms) {
 546             end = ms;
 547         }
 548 
 549         public long getEndTime() {
 550             return end;
 551         }
 552 
 553         public void setProperty(String key, String value) {
 554             props.put(key, value);
 555         }
 556 
 557         public Hashtable getProperties() {
 558             return this.props;
 559         }
 560 
 561         public void addResult(ResultHolder rh) {
 562             results.add(rh);
 563             resultsbykey.put(rh.getKey(), rh);
 564         }
 565 
 566         public Enumeration getKeyEnumeration() {
 567             return new Enumerator();
 568         }
 569 
 570         public Enumeration getResultEnumeration() {
 571             return results.elements();
 572         }
 573 
 574         public ResultHolder getResultByKey(String key) {
 575             return (ResultHolder) resultsbykey.get(key);
 576         }
 577 
 578         public class Enumerator implements Enumeration {
 579             Enumeration raw = getResultEnumeration();
 580 
 581             public boolean hasMoreElements() {
 582                 return raw.hasMoreElements();
 583             }
 584 
 585             public Object nextElement() {
 586                 return ((ResultHolder) raw.nextElement()).getKey();
 587             }
 588         }
 589     }
 590 
 591     public static class ResultHolder {
 592         public static Hashtable commonkeymap = new Hashtable();
 593         public static Hashtable commonkeys = new Hashtable();
 594         public static String commonname;
 595 
 596         ResultSetHolder rsh;
 597         private String name;
 598         private String key;
 599         private String shortkey;
 600         private int numreps;
 601         private int numunits;
 602         private int numruns;
 603         private long total;
 604         private long longest;
 605         private long shortest;
 606         private Hashtable options = new Hashtable();
 607         private Vector times = new Vector();
 608 
 609         public ResultHolder(ResultSetHolder rsh) {
 610             this.rsh = rsh;
 611         }
 612 
 613         public void setName(String name) {
 614             this.name = name;
 615             if (commonname == null) {
 616                 commonname = name;
 617             } else if (!commonname.equals(name)) {
 618                 commonname = "";
 619             }
 620         }
 621 
 622         public String getName() {
 623             return name;
 624         }
 625 
 626         public String getKey() {
 627             if (key == null) {
 628                 key = makeKey(false);
 629             }
 630             return key;
 631         }
 632 
 633         public String getShortKey() {
 634             if (shortkey == null) {
 635                 shortkey = makeKey(true);
 636             }
 637             return shortkey;
 638         }
 639 
 640         private String makeKey(boolean prunecommon) {
 641             String keys[] = new String[options.size()];
 642             Enumeration enum_ = options.keys();
 643             int i = 0;
 644             while (enum_.hasMoreElements()) {
 645                 keys[i++] = (String) enum_.nextElement();
 646             }
 647             sort(keys);
 648             String key = (prunecommon && commonname.equals(name)) ? "" : name;
 649             for (i = 0; i < keys.length; i++) {
 650                 if (!prunecommon || !commonkeys.containsKey(keys[i])) {
 651                     key = key+","+keys[i]+"="+options.get(keys[i]);
 652                 }
 653             }
 654             if (key.length() == 0) {
 655                 key = name;
 656             } else if (key.startsWith(",")) {
 657                 key = key.substring(1);
 658             }
 659             return key;
 660         }
 661 
 662         public void setReps(int numreps) {
 663             this.numreps = numreps;
 664         }
 665 
 666         public int getReps() {
 667             return numreps;
 668         }
 669 
 670         public void setUnits(int numunits) {
 671             this.numunits = numunits;
 672         }
 673 
 674         public int getUnits() {
 675             return numunits;
 676         }
 677 
 678         public void addOption(String key, String value) {
 679             if (this.key != null) {
 680                 throw new InternalError("option added after key was made!");
 681             }
 682             options.put(key, value);
 683             Object commonval = commonkeymap.get(key);
 684             if (commonval == null) {
 685                 commonkeymap.put(key, value);
 686                 commonkeys.put(key, key);
 687             } else if (!commonval.equals(value)) {
 688                 commonkeys.remove(key);
 689             }
 690         }
 691 
 692         public Hashtable getOptions() {
 693             return options;
 694         }
 695 
 696         public void addTime(long ms) {
 697             times.add(new Long(ms));
 698             if (numruns == 0) {
 699                 longest = shortest = ms;
 700             } else {
 701                 if (longest < ms) longest = ms;
 702                 if (shortest > ms) shortest = ms;
 703             }
 704             total += ms;
 705             numruns++;
 706         }
 707 
 708         public double getSpread() {
 709             return calcPercent(shortest, longest - shortest);
 710         }
 711 
 712         public double getScore() {
 713             double score = numreps;
 714             if (numunits > 0) {
 715                 score *= numunits;
 716             }
 717             long divisor;
 718             if (mode == BEST) {
 719                 divisor = shortest;
 720             } else if (mode == WORST) {
 721                 divisor = longest;
 722             } else if (mode == AVERAGE || numruns < 3) {
 723                 score *= numruns;
 724                 divisor = total;
 725             } else {
 726                 score *= (numruns-2);
 727                 divisor = (total - longest - shortest);
 728             }
 729             score /= divisor;
 730             return score;
 731         }
 732 
 733         public double getBestScore() {
 734             double score = numreps;
 735             if (numunits > 0) {
 736                 score *= numunits;
 737             }
 738             return score / shortest;
 739         }
 740 
 741         public Vector getAllScores() {
 742             Vector scores = new Vector();
 743 
 744             double score = numreps;
 745             if (numunits > 0) {
 746                 score *= numunits;
 747             }
 748             if (mode == BEST) {
 749                 scores.add(new Double(score / shortest));
 750             } else if (mode == WORST) {
 751                 scores.add(new Double(score / longest));
 752             } else {
 753                 long elimshort, elimlong;
 754                 if (mode == AVERAGE || numruns < 3) {
 755                     elimshort = elimlong = -1;
 756                 } else {
 757                     elimshort = shortest;
 758                     elimlong = longest;
 759                 }
 760                 for (int i = 0; i < times.size(); i++) {
 761                     long time = ((Long) times.get(i)).longValue();
 762                     if (time == elimshort) {
 763                         elimshort = -1;
 764                         continue;
 765                     }
 766                     if (time == elimlong) {
 767                         elimlong = -1;
 768                         continue;
 769                     }
 770                     scores.add(new Double(score / time));
 771                 }
 772             }
 773             return scores;
 774         }
 775     }
 776 
 777     public static double calcPercent(double base, double val) {
 778         val /= base;
 779         val *= 10000;
 780         val = Math.rint(val);
 781         return val / 100;
 782     }
 783 
 784     public static String format(double val) {
 785         long lval = (long) val;
 786         String ret = String.valueOf(lval);
 787         int digits = ret.length();
 788         if (digits > 17) {
 789             ret = String.valueOf(val);
 790         } else {
 791             val -= lval;
 792             String fraction = String.valueOf(val);
 793             fraction = fraction.substring(fraction.indexOf('.'));
 794             ret += fraction;
 795             int len = digits+5;
 796             if (len < 10) len = 10;
 797             len++;
 798             if (ret.length() > len) {
 799                 ret = ret.substring(0, len);
 800             }
 801         }
 802         return ret;
 803     }
 804 
 805     public static void sort(String strs[]) {
 806         for (int i = 1; i < strs.length; i++) {
 807             for (int j = i; j > 0; j--) {
 808                 if (strs[j].compareTo(strs[j-1]) >= 0) {
 809                     break;
 810                 }
 811                 String tmp = strs[j-1];
 812                 strs[j-1] = strs[j];
 813                 strs[j] = tmp;
 814             }
 815         }
 816     }
 817 
 818     public static void setMode(int mode) {
 819         if(mode >= BEST && mode <= MIDAVG) {
 820             J2DAnalyzer.mode = mode;
 821         }
 822         else {
 823             J2DAnalyzer.mode = MIDAVG;
 824         }
 825     }
 826 }