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