view j2se/src/share/demo/java2d/J2DBench/src/j2dbench/report/J2DAnalyzer.java @ 2:16f2b6c91171 trunk

[svn] Load openjdk/jdk7/b14 into jdk/trunk.
author xiomara
date Fri, 22 Jun 2007 00:46:43 +0000
parents a4ed3fb96592
children
line wrap: on
line source

/*
 * Copyright 2002-2007 Sun Microsystems, Inc.  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 Sun Microsystems 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.
 */

package j2dbench.report;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;

public class J2DAnalyzer {
    static Vector results = new Vector();
    static GroupResultSetHolder groupHolder;

    static final int BEST = 1;    /* The best score */
    static final int WORST = 2;   /* The worst score */
    static final int AVERAGE = 3; /* Average of all scores */
    static final int MIDAVG = 4;  /* Average of all but the best and worst */

    static int mode = MIDAVG;

    public static void usage(PrintStream out) {
	out.println("usage:");
	out.println("    java -jar J2DAnalyzer.jar [Option]*");
	out.println();
	out.println("where options are any of the following in any order:");
	out.println("   -Help|-Usage          "+
		    "print out this usage statement");
	out.println("   -Group:<groupname>    "+
		    "the following result sets are combined into a group");
	out.println("   -NoGroup              "+
		    "the following result sets stand on their own");
	out.println("   -Graph                "+
		    "graph the results visually (using lines of *'s)");
	out.println("   -Best                 "+
		    "use best time within a resultset");
	out.println("   -Worst                "+
		    "use worst time within a resultset");
	out.println("   -Average|-Avg         "+
		    "use average of all times within a resultset");
	out.println("   -MidAverage|-MidAvg   "+
		    "like -Average but ignore best and worst times");
	out.println("   <resultfilename>      "+
		    "load in results from named file");
	out.println();
	out.println("results within a result set "+
		    "use Best/Worst/Average mode");
	out.println("results within a group "+
		    "are best of all result sets in that group");
    }

    public static void main(String argv[]) {
	boolean gavehelp = false;
        boolean graph = false;
        if (argv.length > 0 && argv[0].equalsIgnoreCase("-html")) {
            String newargs[] = new String[argv.length-1];
            System.arraycopy(argv, 1, newargs, 0, newargs.length);
            HTMLSeriesReporter.main(newargs);
            return;
        }
	for (int i = 0; i < argv.length; i++) {
	    String arg = argv[i];
	    if (arg.regionMatches(true, 0, "-Group:", 0, 7)) {
		groupHolder = new GroupResultSetHolder();
		groupHolder.setTitle(arg.substring(7));
		results.add(groupHolder);
	    } else if (arg.equalsIgnoreCase("-NoGroup")) {
		groupHolder = null;
	    } else if (arg.equalsIgnoreCase("-Graph")) {
		graph = true;
	    } else if (arg.equalsIgnoreCase("-Best")) {
		mode = BEST;
	    } else if (arg.equalsIgnoreCase("-Worst")) {
		mode = WORST;
	    } else if (arg.equalsIgnoreCase("-Average") ||
		       arg.equalsIgnoreCase("-Avg"))
	    {
		mode = AVERAGE;
	    } else if (arg.equalsIgnoreCase("-MidAverage") ||
		       arg.equalsIgnoreCase("-MidAvg"))
	    {
		mode = MIDAVG;
	    } else if (arg.equalsIgnoreCase("-Help") ||
		       arg.equalsIgnoreCase("-Usage"))
	    {
		usage(System.out);
		gavehelp = true;
	    } else {
		readResults(argv[i]);
	    }
	}

	if (results.size() == 0) {
	    if (!gavehelp) {
		System.err.println("No results loaded");
		usage(System.err);
	    }
	    return;
	}

	int numsets = results.size();
	double totalscore[] = new double[numsets];
	int numwins[] = new int[numsets];
	int numties[] = new int[numsets];
	int numloss[] = new int[numsets];
	int numtests[] = new int[numsets];
	double bestscore[] = new double[numsets];
	double worstscore[] = new double[numsets];
	double bestspread[] = new double[numsets];
	double worstspread[] = new double[numsets];
	for (int i = 0; i < numsets; i++) {
	    bestscore[i] = Double.NEGATIVE_INFINITY;
	    worstscore[i] = Double.POSITIVE_INFINITY;
	    bestspread[i] = Double.POSITIVE_INFINITY;
	    worstspread[i] = Double.NEGATIVE_INFINITY;
	}

	ResultSetHolder base = (ResultSetHolder) results.elementAt(0);
	Enumeration enum_ = base.getKeyEnumeration();
	Vector keyvector = new Vector();
	while (enum_.hasMoreElements()) {
	    keyvector.add(enum_.nextElement());
	}
	String keys[] = new String[keyvector.size()];
	keyvector.copyInto(keys);
	sort(keys);
	enum_ = ResultHolder.commonkeys.keys();
	System.out.println("Options common across all tests:");
	if (ResultHolder.commonname != null &&
	    ResultHolder.commonname.length() != 0)
	{
	    System.out.println("  testname="+ResultHolder.commonname);
	}
	while (enum_.hasMoreElements()) {
	    Object key = enum_.nextElement();
	    System.out.println("  "+key+"="+ResultHolder.commonkeymap.get(key));
	}
	System.out.println();
	for (int k = 0; k < keys.length; k++) {
	    String key = keys[k];
	    ResultHolder rh = base.getResultByKey(key);
	    double score = rh.getScore();
	    System.out.println(rh.getShortKey()+":");
            double maxscore = score;
            if (graph) {
                for (int i = 0; i < numsets; i++) {
                    ResultSetHolder rsh =
                        (ResultSetHolder) results.elementAt(i);
                    ResultHolder rh2 = rsh.getResultByKey(key);
                    if (rh2 != null) {
                        maxscore = Math.max(maxscore, rh2.getBestScore());
                    }
                }
            }
	    for (int i = 0; i < numsets; i++) {
		ResultSetHolder rsh = (ResultSetHolder) results.elementAt(i);
		System.out.print(rsh.getTitle()+": ");
		ResultHolder rh2 = rsh.getResultByKey(key);
		if (rh2 == null) {
		    System.out.println("not run");
		} else {
		    double score2 = rh2.getScore();
		    double percent = calcPercent(score, score2);
		    numtests[i]++;
		    if (percent < 97.5) {
			numloss[i]++;
		    } else if (percent > 102.5) {
			numwins[i]++;
		    } else {
			numties[i]++;
		    }
		    totalscore[i] += score2;
		    if (bestscore[i] < percent) {
			bestscore[i] = percent;
		    }
		    if (worstscore[i] > percent) {
			worstscore[i] = percent;
		    }
		    double spread = rh2.getSpread();
		    if (bestspread[i] > spread) {
			bestspread[i] = spread;
		    }
		    if (worstspread[i] < spread) {
			worstspread[i] = spread;
		    }
		    System.out.print(format(score2));
		    System.out.print(" (var="+spread+"%)");
		    System.out.print(" ("+percent+"%)");
                    System.out.println();
                    if (graph) {
                        int maxlen = 60;
                        int avgpos =
                            (int) Math.round(maxlen * score / maxscore);
                        Vector scores = rh2.getAllScores();
                        for (int j = 0; j < scores.size(); j++) {
                            double s = ((Double) scores.get(j)).doubleValue();
                            int len = (int) Math.round(maxlen * s / maxscore);
                            int pos = 0;
                            while (pos < len) {
                                System.out.print(pos == avgpos ? '|' : '*');
                                pos++;
                            }
                            while (pos <= avgpos) {
                                System.out.print(pos == avgpos ? '|' : ' ');
                                pos++;
                            }
                            System.out.println();
                        }
                    }
		}
	    }
	}
	System.out.println();
	System.out.println("Summary:");
	for (int i = 0; i < numsets; i++) {
	    ResultSetHolder rsh = (ResultSetHolder) results.elementAt(i);
	    System.out.println("  "+rsh.getTitle()+": ");
	    if (numtests[i] == 0) {
		System.out.println("    No tests matched reference results");
	    } else {
		double overallscore = totalscore[i]/numtests[i];
		System.out.println("    Number of tests:  "+numtests[i]);
		System.out.println("    Overall average:  "+overallscore);
		System.out.println("    Best spread:      "+bestspread[i]+
				   "% variance");
		System.out.println("    Worst spread:     "+worstspread[i]+
				   "% variance");
		if (i == 0) {
		    System.out.println("    (Basis for results comparison)");
		} else {
		    System.out.println("    Comparison to basis:");
		    System.out.println("      Best result:      "+bestscore[i]+
				       "% of basis");
		    System.out.println("      Worst result:     "+worstscore[i]+
				       "% of basis");
		    System.out.println("      Number of wins:   "+numwins[i]);
		    System.out.println("      Number of ties:   "+numties[i]);
		    System.out.println("      Number of losses: "+numloss[i]);
		}
	    }
	    System.out.println();
	}
    }

    public static void readResults(String filename) {
	BufferedReader in;
	try {
	    in = new BufferedReader(new FileReader(filename));
	    readResults(in);
	} catch (IOException e) {
	    System.out.println(e);
	    return;
	}
    }

    public static void addResultSet(ResultSetHolder rs) {
	if (groupHolder == null) {
	    results.add(rs);
	} else {
	    groupHolder.addResultSet(rs);
	}
    }

    public static void readResults(BufferedReader in)
	throws IOException
    {
	String xmlver = in.readLine();
	if (xmlver == null || !xmlver.startsWith("<?xml version=\"1.0\"")) {
	    return;
	}
	while (true) {
	    String rsline = in.readLine();
	    if (rsline == null) {
		break;
	    }
	    rsline = rsline.trim();
	    if (rsline.startsWith("<result-set version=")) {
		String title = getStringAttribute(rsline, "name");
		if (title == null) {
		    title = "No title";
		}
		SingleResultSetHolder srs = new SingleResultSetHolder();
		srs.setTitle(title);
		readResultSet(in, srs);
		addResultSet(srs);
	    }
	}
    }

    public static void readResultSet(BufferedReader in,
				     SingleResultSetHolder srs)
	throws IOException
    {
	String line;
	while ((line = in.readLine()) != null) {
	    line = line.trim();
	    if (line.startsWith("<test-desc>")) {
		int index = line.indexOf("<", 11);
		if (index < 0) {
		    index = line.length();
		}
		line = line.substring(11, index);
		srs.setDescription(line);
	    } else if (line.startsWith("<sys-prop")) {
		String key = getStringAttribute(line, "key");
		String val = getStringAttribute(line, "value");
		if (key != null && val != null) {
		    srs.setProperty(key, val);
		}
	    } else if (line.startsWith("<test-date")) {
		srs.setStartTime(getLongAttribute(line, "start"));
		srs.setEndTime(getLongAttribute(line, "end"));
	    } else if (line.startsWith("<result")) {
		int numreps = getIntAttribute(line, "num-reps");
		int numunits = getIntAttribute(line, "num-units");
		String name = getStringAttribute(line, "name");
		if (numreps > 0 && numunits >= 0 && name != null) {
		    ResultHolder rh = new ResultHolder(srs);
		    rh.setName(name);
		    rh.setReps(numreps);
		    rh.setUnits(numunits);
		    readResult(in, rh);
		    srs.addResult(rh);
		}
	    } else if (line.equals("</result-set>")) {
		break;
	    } else {
		System.err.println("Unrecognized line in Result-Set: "+line);
	    }
	}
    }

    public static void readResult(BufferedReader in, ResultHolder rh)
	throws IOException
    {
	String line;
	while ((line = in.readLine()) != null) {
	    line = line.trim();
	    if (line.startsWith("<option")) {
		String key = getStringAttribute(line, "key");
		String val = getStringAttribute(line, "value");
		if (key != null && val != null) {
		    rh.addOption(key, val);
		}
	    } else if (line.startsWith("<time")) {
		long ms = getLongAttribute(line, "value");
		if (ms >= 0) {
		    rh.addTime(ms);
		}
	    } else if (line.equals("</result>")) {
		break;
	    } else {
		System.err.println("Unrecognized line in Result: "+line);
	    }
	}
    }

    public static String getStringAttribute(String line, String attrname) {
	int index = line.indexOf(attrname+"=");
	if (index < 0) {
	    return null;
	}
	index += attrname.length()+1;
	int endindex;
	if (line.charAt(index) == '\"') {
	    index++;
	    endindex = line.indexOf('\"', index);
	} else {
	    endindex = -1;
	}
	if (endindex < 0) {
	    endindex = line.indexOf(' ', index);
	}
	if (endindex < 0) {
	    endindex = line.indexOf('>', index);
	}
	if (endindex < 0) {
	    endindex = line.length();
	}
	return line.substring(index, endindex);
    }

    public static long getLongAttribute(String line, String attrname) {
	String val = getStringAttribute(line, attrname);
	if (val == null) {
	    return -1;
	}
	try {
	    return Long.parseLong(val);
	} catch (NumberFormatException e) {
	    return -1;
	}
    }

    public static int getIntAttribute(String line, String attrname) {
	String val = getStringAttribute(line, attrname);
	if (val == null) {
	    return -1;
	}
	try {
	    return Integer.parseInt(val);
	} catch (NumberFormatException e) {
	    return -1;
	}
    }

    public abstract static class ResultSetHolder {
	private String title;

	public void setTitle(String title) {
	    this.title = title;
	}

	public String getTitle() {
	    return title;
	}

	public abstract Enumeration getKeyEnumeration();

	public abstract Enumeration getResultEnumeration();

	public abstract ResultHolder getResultByKey(String key);
    }

    public static class GroupResultSetHolder extends ResultSetHolder {
	private Vector members = new Vector();
	private Hashtable allresultkeys = new Hashtable();

	public void addResultSet(ResultSetHolder rsh) {
	    members.add(rsh);
	    Enumeration enum_ = rsh.getResultEnumeration();
	    while (enum_.hasMoreElements()) {
		ResultHolder rh = (ResultHolder) enum_.nextElement();
		String key = rh.getKey();
		allresultkeys.put(key, key);
	    }
	}

	private ResultSetHolder getResultSet(int index) {
	    return (ResultSetHolder) members.elementAt(index);
	}

	public Enumeration getKeyEnumeration() {
	    return allresultkeys.keys();
	}

	public Enumeration getResultEnumeration() {
	    return new Enumerator();
	}

	public ResultHolder getResultByKey(String key) {
	    ResultHolder best = null;
	    double bestscore = 0.0;
	    for (int i = 0; i < members.size(); i++) {
		ResultHolder cur = getResultSet(i).getResultByKey(key);
		if (cur != null) {
		    double curscore = cur.getScore();
		    if (best == null || curscore > bestscore) {
			best = cur;
			bestscore = curscore;
		    }
		}
	    }
	    return best;
	}

	public class Enumerator implements Enumeration {
	    Enumeration raw = getKeyEnumeration();

	    public boolean hasMoreElements() {
		return raw.hasMoreElements();
	    }

	    public Object nextElement() {
		return getResultByKey((String) raw.nextElement());
	    }
	}
    }

    public static class SingleResultSetHolder extends ResultSetHolder {
	private String desc;
	private long start;
	private long end;
	private Hashtable props = new Hashtable();
	private Vector results = new Vector();
	private Hashtable resultsbykey = new Hashtable();

	public void setDescription(String desc) {
	    this.desc = desc;
	}

        public String getDescription() {
            return desc;
        }

	public void setStartTime(long ms) {
	    start = ms;
	}

        public long getStartTime() {
            return start;
        }

	public void setEndTime(long ms) {
	    end = ms;
	}

        public long getEndTime() {
            return end;
        }

	public void setProperty(String key, String value) {
	    props.put(key, value);
	}

        public Hashtable getProperties() {
            return this.props;
        }

	public void addResult(ResultHolder rh) {
	    results.add(rh);
	    resultsbykey.put(rh.getKey(), rh);
	}

	public Enumeration getKeyEnumeration() {
	    return new Enumerator();
	}

	public Enumeration getResultEnumeration() {
	    return results.elements();
	}

	public ResultHolder getResultByKey(String key) {
	    return (ResultHolder) resultsbykey.get(key);
	}

	public class Enumerator implements Enumeration {
	    Enumeration raw = getResultEnumeration();

	    public boolean hasMoreElements() {
		return raw.hasMoreElements();
	    }

	    public Object nextElement() {
		return ((ResultHolder) raw.nextElement()).getKey();
	    }
	}
    }

    public static class ResultHolder {
	public static Hashtable commonkeymap = new Hashtable();
	public static Hashtable commonkeys = new Hashtable();
	public static String commonname;

	ResultSetHolder rsh;
	private String name;
	private String key;
	private String shortkey;
	private int numreps;
	private int numunits;
	private int numruns;
	private long total;
	private long longest;
	private long shortest;
	private Hashtable options = new Hashtable();
	private Vector times = new Vector();

	public ResultHolder(ResultSetHolder rsh) {
	    this.rsh = rsh;
	}

	public void setName(String name) {
	    this.name = name;
	    if (commonname == null) {
		commonname = name;
	    } else if (!commonname.equals(name)) {
		commonname = "";
	    }
	}

	public String getName() {
	    return name;
	}

	public String getKey() {
	    if (key == null) {
		key = makeKey(false);
	    }
	    return key;
	}

	public String getShortKey() {
	    if (shortkey == null) {
		shortkey = makeKey(true);
	    }
	    return shortkey;
	}

	private String makeKey(boolean prunecommon) {
	    String keys[] = new String[options.size()];
	    Enumeration enum_ = options.keys();
	    int i = 0;
	    while (enum_.hasMoreElements()) {
		keys[i++] = (String) enum_.nextElement();
	    }
	    sort(keys);
	    String key = (prunecommon && commonname.equals(name)) ? "" : name;
	    for (i = 0; i < keys.length; i++) {
		if (!prunecommon || !commonkeys.containsKey(keys[i])) {
		    key = key+","+keys[i]+"="+options.get(keys[i]);
		}
	    }
	    if (key.length() == 0) {
		key = name;
	    } else if (key.startsWith(",")) {
		key = key.substring(1);
	    }
	    return key;
	}

	public void setReps(int numreps) {
	    this.numreps = numreps;
	}

        public int getReps() {
            return numreps;
        }

	public void setUnits(int numunits) {
	    this.numunits = numunits;
	}

        public int getUnits() {
            return numunits;
        }

	public void addOption(String key, String value) {
	    if (this.key != null) {
		throw new InternalError("option added after key was made!");
	    }
	    options.put(key, value);
	    Object commonval = commonkeymap.get(key);
	    if (commonval == null) {
		commonkeymap.put(key, value);
		commonkeys.put(key, key);
	    } else if (!commonval.equals(value)) {
		commonkeys.remove(key);
	    }
	}

        public Hashtable getOptions() {
            return options;
        }

	public void addTime(long ms) {
	    times.add(new Long(ms));
	    if (numruns == 0) {
		longest = shortest = ms;
	    } else {
		if (longest < ms) longest = ms;
		if (shortest > ms) shortest = ms;
	    }
	    total += ms;
	    numruns++;
	}

	public double getSpread() {
	    return calcPercent(shortest, longest - shortest);
	}

	public double getScore() {
	    double score = numreps;
	    if (numunits > 0) {
		score *= numunits;
	    }
	    long divisor;
	    if (mode == BEST) {
		divisor = shortest;
	    } else if (mode == WORST) {
		divisor = longest;
	    } else if (mode == AVERAGE || numruns < 3) {
		score *= numruns;
		divisor = total;
	    } else {
		score *= (numruns-2);
		divisor = (total - longest - shortest);
	    }
	    score /= divisor;
	    return score;
	}

        public double getBestScore() {
	    double score = numreps;
	    if (numunits > 0) {
		score *= numunits;
	    }
	    return score / shortest;
        }

        public Vector getAllScores() {
            Vector scores = new Vector();

	    double score = numreps;
	    if (numunits > 0) {
		score *= numunits;
	    }
	    if (mode == BEST) {
                scores.add(new Double(score / shortest));
	    } else if (mode == WORST) {
                scores.add(new Double(score / longest));
	    } else {
                long elimshort, elimlong;
                if (mode == AVERAGE || numruns < 3) {
                    elimshort = elimlong = -1;
                } else {
                    elimshort = shortest;
                    elimlong = longest;
                }
                for (int i = 0; i < times.size(); i++) {
                    long time = ((Long) times.get(i)).longValue();
                    if (time == elimshort) {
                        elimshort = -1;
                        continue;
                    }
                    if (time == elimlong) {
                        elimlong = -1;
                        continue;
                    }
                    scores.add(new Double(score / time));
                }
	    }
	    return scores;
        }
    }

    public static double calcPercent(double base, double val) {
	val /= base;
	val *= 10000;
	val = Math.rint(val);
	return val / 100;
    }

    public static String format(double val) {
	long lval = (long) val;
	String ret = String.valueOf(lval);
	int digits = ret.length();
	if (digits > 17) {
	    ret = String.valueOf(val);
	} else {
	    val -= lval;
	    String fraction = String.valueOf(val);
	    fraction = fraction.substring(fraction.indexOf('.'));
	    ret += fraction;
	    int len = digits+5;
	    if (len < 10) len = 10;
	    len++;
	    if (ret.length() > len) {
		ret = ret.substring(0, len);
	    }
	}
	return ret;
    }

    public static void sort(String strs[]) {
	for (int i = 1; i < strs.length; i++) {
	    for (int j = i; j > 0; j--) {
		if (strs[j].compareTo(strs[j-1]) >= 0) {
		    break;
		}
		String tmp = strs[j-1];
		strs[j-1] = strs[j];
		strs[j] = tmp;
	    }
	}
    }

    public static void setMode(int mode) {
        if(mode >= BEST && mode <= MIDAVG) {
            J2DAnalyzer.mode = mode;
        }
        else {
            J2DAnalyzer.mode = MIDAVG;
        }
    }
}