3789983e89
Reviewed-by: darcy, ihse
236 lines
8.0 KiB
Java
236 lines
8.0 KiB
Java
/*
|
|
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
package bench;
|
|
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.StreamTokenizer;
|
|
import java.io.IOException;
|
|
import java.util.Vector;
|
|
|
|
|
|
/**
|
|
* Benchmark harness. Responsible for parsing config file and running
|
|
* benchmarks.
|
|
*/
|
|
public class Harness {
|
|
|
|
BenchInfo[] binfo;
|
|
|
|
/**
|
|
* Create new benchmark harness with given configuration and reporter.
|
|
* Throws ConfigFormatException if there was an error parsing the config
|
|
* file.
|
|
* <p>
|
|
* <b>Config file syntax:</b>
|
|
* <p>
|
|
* '#' marks the beginning of a comment. Blank lines are ignored. All
|
|
* other lines should adhere to the following format:
|
|
* <pre>
|
|
* <weight> <name> <class> [<args>]
|
|
* </pre>
|
|
* <weight> is a floating point value which is multiplied times the
|
|
* benchmark's execution time to determine its weighted score. The
|
|
* total score of the benchmark suite is the sum of all weighted scores
|
|
* of its benchmarks.
|
|
* <p>
|
|
* <name> is a name used to identify the benchmark on the benchmark
|
|
* report. If the name contains whitespace, the quote character '"' should
|
|
* be used as a delimiter.
|
|
* <p>
|
|
* <class> is the full name (including the package) of the class
|
|
* containing the benchmark implementation. This class must implement
|
|
* bench.Benchmark.
|
|
* <p>
|
|
* [<args>] is a variable-length list of runtime arguments to pass to
|
|
* the benchmark. Arguments containing whitespace should use the quote
|
|
* character '"' as a delimiter.
|
|
* <p>
|
|
* <b>Example:</b>
|
|
* <pre>
|
|
* 3.5 "My benchmark" bench.serial.Test first second "third arg"
|
|
* </pre>
|
|
*/
|
|
public Harness(InputStream in) throws IOException, ConfigFormatException {
|
|
Vector bvec = new Vector();
|
|
StreamTokenizer tokens = new StreamTokenizer(new InputStreamReader(in));
|
|
|
|
tokens.resetSyntax();
|
|
tokens.wordChars(0, 255);
|
|
tokens.whitespaceChars(0, ' ');
|
|
tokens.commentChar('#');
|
|
tokens.quoteChar('"');
|
|
tokens.eolIsSignificant(true);
|
|
|
|
tokens.nextToken();
|
|
while (tokens.ttype != StreamTokenizer.TT_EOF) {
|
|
switch (tokens.ttype) {
|
|
case StreamTokenizer.TT_WORD:
|
|
case '"': // parse line
|
|
bvec.add(parseBenchInfo(tokens));
|
|
break;
|
|
|
|
default: // ignore
|
|
tokens.nextToken();
|
|
break;
|
|
}
|
|
}
|
|
binfo = (BenchInfo[]) bvec.toArray(new BenchInfo[bvec.size()]);
|
|
}
|
|
|
|
BenchInfo parseBenchInfo(StreamTokenizer tokens)
|
|
throws IOException, ConfigFormatException
|
|
{
|
|
float weight = parseBenchWeight(tokens);
|
|
String name = parseBenchName(tokens);
|
|
Benchmark bench = parseBenchClass(tokens);
|
|
String[] args = parseBenchArgs(tokens);
|
|
if (tokens.ttype == StreamTokenizer.TT_EOL)
|
|
tokens.nextToken();
|
|
return new BenchInfo(bench, name, weight, args);
|
|
}
|
|
|
|
float parseBenchWeight(StreamTokenizer tokens)
|
|
throws IOException, ConfigFormatException
|
|
{
|
|
float weight;
|
|
switch (tokens.ttype) {
|
|
case StreamTokenizer.TT_WORD:
|
|
case '"':
|
|
try {
|
|
weight = Float.parseFloat(tokens.sval);
|
|
} catch (NumberFormatException e) {
|
|
throw new ConfigFormatException("illegal weight value \"" +
|
|
tokens.sval + "\" on line " + tokens.lineno());
|
|
}
|
|
tokens.nextToken();
|
|
return weight;
|
|
|
|
default:
|
|
throw new ConfigFormatException("missing weight value on line "
|
|
+ tokens.lineno());
|
|
}
|
|
}
|
|
|
|
String parseBenchName(StreamTokenizer tokens)
|
|
throws IOException, ConfigFormatException
|
|
{
|
|
String name;
|
|
switch (tokens.ttype) {
|
|
case StreamTokenizer.TT_WORD:
|
|
case '"':
|
|
name = tokens.sval;
|
|
tokens.nextToken();
|
|
return name;
|
|
|
|
default:
|
|
throw new ConfigFormatException("missing benchmark name on " +
|
|
"line " + tokens.lineno());
|
|
}
|
|
}
|
|
|
|
Benchmark parseBenchClass(StreamTokenizer tokens)
|
|
throws IOException, ConfigFormatException
|
|
{
|
|
Benchmark bench;
|
|
switch (tokens.ttype) {
|
|
case StreamTokenizer.TT_WORD:
|
|
case '"':
|
|
try {
|
|
Class cls = Class.forName(tokens.sval);
|
|
bench = (Benchmark) cls.newInstance();
|
|
} catch (Exception e) {
|
|
throw new ConfigFormatException("unable to instantiate " +
|
|
"benchmark \"" + tokens.sval + "\" on line " +
|
|
tokens.lineno());
|
|
}
|
|
tokens.nextToken();
|
|
return bench;
|
|
|
|
default:
|
|
throw new ConfigFormatException("missing benchmark class " +
|
|
"name on line " + tokens.lineno());
|
|
}
|
|
}
|
|
|
|
String[] parseBenchArgs(StreamTokenizer tokens)
|
|
throws IOException, ConfigFormatException
|
|
{
|
|
Vector vec = new Vector();
|
|
for (;;) {
|
|
switch (tokens.ttype) {
|
|
case StreamTokenizer.TT_EOF:
|
|
case StreamTokenizer.TT_EOL:
|
|
return (String[]) vec.toArray(new String[vec.size()]);
|
|
|
|
case StreamTokenizer.TT_WORD:
|
|
case '"':
|
|
vec.add(tokens.sval);
|
|
tokens.nextToken();
|
|
break;
|
|
|
|
default:
|
|
throw new ConfigFormatException("unrecognized arg token " +
|
|
"on line " + tokens.lineno());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run benchmarks, writing results to the given reporter.
|
|
*/
|
|
public void runBenchmarks(Reporter reporter, boolean verbose) {
|
|
for (int i = 0; i < binfo.length; i++) {
|
|
if (verbose)
|
|
System.out.println("Running benchmark " + i + " (" +
|
|
binfo[i].getName() + ")");
|
|
try {
|
|
binfo[i].runBenchmark();
|
|
} catch (Exception e) {
|
|
System.err.println("Error: benchmark " + i + " failed: " + e);
|
|
e.printStackTrace();
|
|
}
|
|
cleanup();
|
|
}
|
|
try {
|
|
reporter.writeReport(binfo, System.getProperties());
|
|
} catch (IOException e) {
|
|
System.err.println("Error: failed to write benchmark report");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up method that is invoked after the completion of each benchmark.
|
|
* The default implementation calls System.gc(); subclasses may override
|
|
* this to perform additional cleanup measures.
|
|
*/
|
|
protected void cleanup() {
|
|
System.gc();
|
|
}
|
|
}
|