ICU-2038 sync up to C uoptions/uperf
X-SVN-Rev: 10296
This commit is contained in:
parent
6d93dcd857
commit
9f2f9e147f
@ -7,6 +7,7 @@
|
||||
**********************************************************************
|
||||
*/
|
||||
package com.ibm.icu.dev.test.perf;
|
||||
import com.ibm.icu.dev.tool.UOption;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.text.DecimalFormat;
|
||||
import java.util.List;
|
||||
@ -100,11 +101,19 @@ public abstract class PerfTest {
|
||||
*/
|
||||
private Map availableTests; // NOT static
|
||||
|
||||
/**
|
||||
* A flag determining whether to call gc() once before the test
|
||||
* passes.
|
||||
*/
|
||||
private boolean doPriorGC;
|
||||
// Command-line options set these:
|
||||
protected boolean verbose;
|
||||
protected String sourceDir;
|
||||
protected String fileName;
|
||||
//protected String resolvedFileName;
|
||||
protected String encoding;
|
||||
protected boolean uselen;
|
||||
protected int iterations;
|
||||
protected int passes;
|
||||
protected int time;
|
||||
protected boolean line_mode;
|
||||
protected boolean bulk_mode;
|
||||
protected boolean doPriorGC;
|
||||
|
||||
/**
|
||||
* Subclasses of PerfTest will need to create subclasses of
|
||||
@ -112,7 +121,7 @@ public abstract class PerfTest {
|
||||
* be timed. They then call setTestFunction() in their "Test..."
|
||||
* method to establish this as the current test functor.
|
||||
*/
|
||||
public abstract class Function {
|
||||
public abstract static class Function {
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to do the action to be
|
||||
@ -121,11 +130,26 @@ public abstract class PerfTest {
|
||||
public abstract void call();
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to return positive
|
||||
* Subclasses may implement this method to return positive
|
||||
* integer indicating the number of operations in a single
|
||||
* call to this object's call() method.
|
||||
* call to this object's call() method. If subclasses do not
|
||||
* override this method, the default implementation returns 1.
|
||||
*/
|
||||
public abstract long getOperationsPerIteration();
|
||||
public long getOperationsPerIteration() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may implement this method to return either positive
|
||||
* or negative integer indicating the number of events in a single
|
||||
* call to this object's call() method. If subclasses do not
|
||||
* override this method, the default implementation returns -1,
|
||||
* indicating that events are not applicable to this test.
|
||||
* e.g: Number of breaks / iterations for break iterator
|
||||
*/
|
||||
public long getEventsPerIteration() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call call() n times in a tight loop and return the elapsed
|
||||
@ -144,12 +168,23 @@ public abstract class PerfTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception indicating a usage error.
|
||||
*/
|
||||
public static class UsageException extends Exception {
|
||||
public UsageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UsageException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
protected PerfTest() {
|
||||
availableTests = null;
|
||||
doPriorGC = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,6 +199,42 @@ public abstract class PerfTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* These must be kept in sync with getOptions().
|
||||
*/
|
||||
static final int HELP1 = 0;
|
||||
static final int HELP2 = 1;
|
||||
static final int VERBOSE = 2;
|
||||
static final int SOURCEDIR = 3;
|
||||
static final int ENCODING = 4;
|
||||
static final int USELEN = 5;
|
||||
static final int FILE_NAME = 6;
|
||||
static final int PASSES = 7;
|
||||
static final int ITERATIONS = 8;
|
||||
static final int TIME = 9;
|
||||
static final int LINE_MODE = 10;
|
||||
static final int BULK_MODE = 11;
|
||||
static final int GARBAGE_COLLECT = 11;
|
||||
|
||||
UOption[] getOptions() {
|
||||
return new UOption[] {
|
||||
UOption.HELP_H(),
|
||||
UOption.HELP_QUESTION_MARK(),
|
||||
UOption.VERBOSE(),
|
||||
UOption.SOURCEDIR(),
|
||||
UOption.ENCODING(),
|
||||
UOption.DEF( "uselen", 'u', UOption.NO_ARG),
|
||||
UOption.DEF( "file-name", 'f', UOption.REQUIRES_ARG),
|
||||
UOption.DEF( "passes", 'p', UOption.REQUIRES_ARG),
|
||||
UOption.DEF( "iterations", 'i', UOption.REQUIRES_ARG),
|
||||
UOption.DEF( "time", 't', UOption.REQUIRES_ARG),
|
||||
UOption.DEF( "line-mode", 'l', UOption.NO_ARG),
|
||||
UOption.DEF( "bulk-mode", 'b', UOption.NO_ARG),
|
||||
|
||||
UOption.DEF( "gc", 'g', UOption.NO_ARG),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method in their main(). run() will
|
||||
* in turn call setup() with any arguments it does not parse.
|
||||
@ -173,54 +244,92 @@ public abstract class PerfTest {
|
||||
*/
|
||||
protected final void run(String[] args) throws Exception {
|
||||
ArrayList methodList = new ArrayList();
|
||||
ArrayList countList = new ArrayList();
|
||||
Method meth = null;
|
||||
ArrayList iterationCounts = new ArrayList();
|
||||
|
||||
availableTests = null;
|
||||
doPriorGC = false;
|
||||
encoding = "";
|
||||
uselen = false;
|
||||
fileName = null;
|
||||
sourceDir = null;
|
||||
//lines = null;
|
||||
line_mode = false;
|
||||
//buffer = null;
|
||||
//bufferLen = 0;
|
||||
verbose = false;
|
||||
bulk_mode = false;
|
||||
passes = iterations = time = 0;
|
||||
|
||||
UOption[] options = getOptions();
|
||||
int remainingArgc = UOption.parseArgs(args, options);
|
||||
|
||||
if(args.length==0 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
|
||||
throw new UsageException();
|
||||
}
|
||||
|
||||
if(options[VERBOSE].doesOccur) {
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
if(options[SOURCEDIR].doesOccur) {
|
||||
sourceDir = options[SOURCEDIR].value;
|
||||
}
|
||||
|
||||
if(options[ENCODING].doesOccur) {
|
||||
encoding = options[ENCODING].value;
|
||||
}
|
||||
|
||||
if(options[USELEN].doesOccur) {
|
||||
uselen = true;
|
||||
}
|
||||
|
||||
if(options[FILE_NAME].doesOccur){
|
||||
fileName = options[FILE_NAME].value;
|
||||
}
|
||||
|
||||
if (options[TIME].doesOccur && options[ITERATIONS].doesOccur) {
|
||||
throw new UsageException("Cannot specify both time and iterations");
|
||||
}
|
||||
|
||||
if(options[PASSES].doesOccur) {
|
||||
passes = Integer.parseInt(options[PASSES].value);
|
||||
}
|
||||
|
||||
if(options[ITERATIONS].doesOccur) {
|
||||
iterations = Integer.parseInt(options[ITERATIONS].value);
|
||||
time =0;
|
||||
}
|
||||
|
||||
if(options[TIME].doesOccur) {
|
||||
time = Integer.parseInt(options[TIME].value);
|
||||
iterations = 0;
|
||||
}
|
||||
|
||||
if (options[LINE_MODE].doesOccur && options[BULK_MODE].doesOccur) {
|
||||
throw new UsageException("Cannot specify both line mode and bulk mode");
|
||||
}
|
||||
|
||||
if(options[LINE_MODE].doesOccur) {
|
||||
line_mode = true;
|
||||
bulk_mode = false;
|
||||
}
|
||||
|
||||
if(options[BULK_MODE].doesOccur) {
|
||||
bulk_mode = true;
|
||||
line_mode = false;
|
||||
}
|
||||
|
||||
if(options[GARBAGE_COLLECT].doesOccur) {
|
||||
doPriorGC = true;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
for (i=0; i<args.length; ++i) {
|
||||
if (args[i].equals("-")) {
|
||||
// end of our options; the rest go to setup()
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (args[i].equalsIgnoreCase("-gc")) {
|
||||
doPriorGC = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args[i].equalsIgnoreCase("-nogc")) {
|
||||
doPriorGC = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// is args[i] a number?
|
||||
try {
|
||||
int n = Integer.parseInt(args[i]);
|
||||
// >0 and <0 are okay, but 0 is illegal
|
||||
if (n == 0) {
|
||||
throw new RuntimeException("Iteration count(s) may not be zero");
|
||||
}
|
||||
if (meth == null) {
|
||||
throw new RuntimeException("Iteration count(s) must follow method name");
|
||||
}
|
||||
iterationCounts.add(new Integer(n));
|
||||
continue;
|
||||
} catch (NumberFormatException e) {}
|
||||
for (i=0; i<remainingArgc; ++i) {
|
||||
|
||||
// is args[i] a method name?
|
||||
Method m = getTestMethod(args[i]);
|
||||
if (m != null) {
|
||||
if (meth != null) {
|
||||
// COPIED below
|
||||
if (iterationCounts.size() < 1) {
|
||||
throw new RuntimeException("Method name must be followed by iteration count(s)");
|
||||
}
|
||||
methodList.add(meth);
|
||||
countList.add(toIntArray(iterationCounts));
|
||||
iterationCounts.clear();
|
||||
}
|
||||
meth = m;
|
||||
methodList.add(m);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -230,26 +339,17 @@ public abstract class PerfTest {
|
||||
break;
|
||||
}
|
||||
|
||||
if (meth != null) {
|
||||
// COPIED from above
|
||||
if (iterationCounts.size() < 1) {
|
||||
throw new RuntimeException("Method name must be followed by iteration count(s)");
|
||||
}
|
||||
methodList.add(meth);
|
||||
countList.add(toIntArray(iterationCounts));
|
||||
}
|
||||
|
||||
if (methodList.size() < 1) {
|
||||
throw new RuntimeException("Must specify at least one method name and count(s)");
|
||||
throw new UsageException("Must specify at least one method name");
|
||||
}
|
||||
|
||||
// Pass remaining arguments, if any, through to the subclass
|
||||
// via setup() method.
|
||||
String[] remainingArgs = new String[args.length - i];
|
||||
for (j=0; i<args.length; ++j) {
|
||||
remainingArgs[j] = args[i++];
|
||||
String[] subclassArgs = new String[remainingArgc - i];
|
||||
for (j=0; i<remainingArgc; ++j) {
|
||||
subclassArgs[j] = args[i++];
|
||||
}
|
||||
setup(remainingArgs);
|
||||
setup(subclassArgs);
|
||||
|
||||
if (doPriorGC) {
|
||||
// Put the heap in a consistent state
|
||||
@ -261,7 +361,6 @@ public abstract class PerfTest {
|
||||
// Run the tests
|
||||
for (i=0; i<methodList.size(); ++i) {
|
||||
meth = (Method) methodList.get(i);
|
||||
int[] counts = (int[]) countList.get(i);
|
||||
|
||||
// Call meth to set up the test
|
||||
long eventsPerCall = -1;
|
||||
@ -275,17 +374,16 @@ public abstract class PerfTest {
|
||||
|
||||
int n;
|
||||
long t;
|
||||
for (j=0; j<counts.length; ++j) {
|
||||
n = counts[j];
|
||||
if (n > 0) {
|
||||
for (j=0; j<passes; ++j) {
|
||||
if (iterations > 0) {
|
||||
// Run specified number of iterations
|
||||
System.out.println("= " + meth.getName() + " begin " + n);
|
||||
t = testFunction.time(n);
|
||||
System.out.println("= " + meth.getName() + " end " + t + " " + testFunction.getOperationsPerIteration());
|
||||
System.out.println("= " + meth.getName() + " begin " + iterations + " iterations");
|
||||
t = testFunction.time(iterations);
|
||||
System.out.println("= " + meth.getName() + " end " + (t/1000.0) + " " + testFunction.getOperationsPerIteration());
|
||||
} else {
|
||||
// Run for specified duration in seconds
|
||||
System.out.println("= " + meth.getName() + " begin " + n);
|
||||
n = -n * 1000; // s => ms
|
||||
System.out.println("= " + meth.getName() + " begin " + time + " seconds");
|
||||
n = time * 1000; // s => ms
|
||||
//System.out.println("# " + meth.getName() + " " + n + " sec");
|
||||
int loops = 0;
|
||||
int failsafe = 1; // last resort for very fast methods
|
||||
@ -304,7 +402,7 @@ public abstract class PerfTest {
|
||||
//System.out.println("# " + meth.getName() + " x " + loops);
|
||||
t = testFunction.time(loops);
|
||||
}
|
||||
System.out.println("= " + meth.getName() + " end " + t + " " + testFunction.getOperationsPerIteration() +
|
||||
System.out.println("= " + meth.getName() + " end " + (t/1000.0) + " " + testFunction.getOperationsPerIteration() +
|
||||
" " + loops);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ package com.ibm.icu.dev.tool;
|
||||
*
|
||||
* This deliberately resembles the icu4c file uoption.[ch].
|
||||
*/
|
||||
class UOption {
|
||||
public class UOption {
|
||||
|
||||
// Deliberated public data members
|
||||
public String longName;
|
||||
@ -57,9 +57,9 @@ class UOption {
|
||||
* Create a UOption with the given attributes.
|
||||
* Synonym for create(), for C compatibility.
|
||||
*/
|
||||
public static UOption UOPTION_DEF(String aLongName,
|
||||
char aShortName,
|
||||
int hasArgument) {
|
||||
public static UOption DEF(String aLongName,
|
||||
char aShortName,
|
||||
int hasArgument) {
|
||||
return create(aLongName, aShortName, hasArgument);
|
||||
}
|
||||
|
||||
@ -129,12 +129,16 @@ class UOption {
|
||||
* the parser returns with the negative index of the argv[] entry
|
||||
* where the error was detected.
|
||||
*
|
||||
* @param argv This parameter is modified
|
||||
* @param options This parameter is modified
|
||||
* @param argv this parameter is modified
|
||||
* @param start the first argument in argv[] to examine. Must be
|
||||
* 0..argv.length-1. Arguments from 0..start-1 are ignored.
|
||||
* @param options this parameter is modified
|
||||
* @return the number of unprocessed arguments in argv[], including
|
||||
* arguments 0..start-1.
|
||||
*/
|
||||
public static int parseArgs(String argv[], UOption options[]) {
|
||||
public static int parseArgs(String argv[], int start, UOption options[]) {
|
||||
String arg;
|
||||
int i=0, remaining=0;
|
||||
int i=start, remaining=start;
|
||||
char c;
|
||||
boolean stopOptions=false;
|
||||
|
||||
@ -235,6 +239,13 @@ class UOption {
|
||||
return remaining;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method.
|
||||
*/
|
||||
public static int parseArgs(String argv[], UOption options[]) {
|
||||
return parseArgs(argv, 0, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user