+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 2002-2006, International Business Machines Corporation and
+ * Copyright (c) 2002-2012, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
+// Defines _XOPEN_SOURCE for access to POSIX functions.
+// Must be before any other #includes.
+#include "uposixdefs.h"
+
#include "unicode/uperf.h"
#include "uoptions.h"
#include "cmemory.h"
#include <stdlib.h>
#if !UCONFIG_NO_CONVERSION
+
+UPerfFunction::~UPerfFunction() {}
+
static const char delim = '/';
static int32_t execCount = 0;
UPerfTest* UPerfTest::gTest = NULL;
"\t-e or --encoding encoding of source files\n"
"\t-u or --uselen perform timing analysis on non-null terminated buffer using length\n"
"\t-f or --file-name file to be used as input data\n"
- "\t-p or --passes Number of passes to be performed. Requires Numeric argument. Cannot be used with --time\n"
+ "\t-p or --passes Number of passes to be performed. Requires Numeric argument.\n"
+ "\t Cannot be used with --time\n"
"\t-i or --iterations Number of iterations to be performed. Requires Numeric argument\n"
- "\t-t or --time Threshold time for looping until in seconds. Requires Numeric argument.Cannot be used with --iterations\n"
+ "\t-t or --time Threshold time for looping until in seconds. Requires Numeric argument.\n"
+ "\t Cannot be used with --iterations\n"
"\t-l or --line-mode The data file should be processed in line mode\n"
- "\t-b or --bulk-mode The data file should be processed in file based. Cannot be used with --line-mode\n"
+ "\t-b or --bulk-mode The data file should be processed in file based.\n"
+ "\t Cannot be used with --line-mode\n"
"\t-L or --locale Locale for the test\n";
enum
TIME,
LINE_MODE,
BULK_MODE,
- LOCALE
+ LOCALE,
+ OPTIONS_COUNT
};
-static UOption options[]={
+static UOption options[OPTIONS_COUNT+20]={
UOPTION_HELP_H,
UOPTION_HELP_QUESTION_MARK,
UOPTION_VERBOSE,
UOPTION_DEF( "locale", 'L', UOPT_REQUIRES_ARG)
};
-UPerfTest::UPerfTest(int32_t argc, const char* argv[], UErrorCode& status){
-
- _argc = argc;
- _argv = argv;
- ucharBuf = NULL;
- encoding = "";
- uselen = FALSE;
- fileName = NULL;
- sourceDir = ".";
- lines = NULL;
- numLines = 0;
- line_mode = TRUE;
- buffer = NULL;
- bufferLen = 0;
- verbose = FALSE;
- bulk_mode = FALSE;
- passes = iterations = time = 0;
- locale = NULL;
-
+UPerfTest::UPerfTest(int32_t argc, const char* argv[], UErrorCode& status)
+ : _argc(argc), _argv(argv), _addUsage(NULL),
+ ucharBuf(NULL), encoding(""),
+ uselen(FALSE),
+ fileName(NULL), sourceDir("."),
+ lines(NULL), numLines(0), line_mode(TRUE),
+ buffer(NULL), bufferLen(0),
+ verbose(FALSE), bulk_mode(FALSE),
+ passes(1), iterations(0), time(0),
+ locale(NULL) {
+ init(NULL, 0, status);
+}
+
+UPerfTest::UPerfTest(int32_t argc, const char* argv[],
+ UOption addOptions[], int32_t addOptionsCount,
+ const char *addUsage,
+ UErrorCode& status)
+ : _argc(argc), _argv(argv), _addUsage(addUsage),
+ ucharBuf(NULL), encoding(""),
+ uselen(FALSE),
+ fileName(NULL), sourceDir("."),
+ lines(NULL), numLines(0), line_mode(TRUE),
+ buffer(NULL), bufferLen(0),
+ verbose(FALSE), bulk_mode(FALSE),
+ passes(1), iterations(0), time(0),
+ locale(NULL) {
+ init(addOptions, addOptionsCount, status);
+}
+
+void UPerfTest::init(UOption addOptions[], int32_t addOptionsCount,
+ UErrorCode& status) {
//initialize the argument list
- U_MAIN_INIT_ARGS(argc, argv);
+ U_MAIN_INIT_ARGS(_argc, _argv);
+
+ resolvedFileName = NULL;
+
+ // add specific options
+ int32_t optionsCount = OPTIONS_COUNT;
+ if (addOptionsCount > 0) {
+ memcpy(options+optionsCount, addOptions, addOptionsCount*sizeof(UOption));
+ optionsCount += addOptionsCount;
+ }
+
//parse the arguments
- _remainingArgc = u_parseArgs(argc, (char**)argv, (int32_t)(sizeof(options)/sizeof(options[0])), options);
+ _remainingArgc = u_parseArgs(_argc, (char**)_argv, optionsCount, options);
+
+ // copy back values for additional options
+ if (addOptionsCount > 0) {
+ memcpy(addOptions, options+OPTIONS_COUNT, addOptionsCount*sizeof(UOption));
+ }
// Now setup the arguments
- if(argc==1 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
+ if(_argc==1 || options[HELP1].doesOccur || options[HELP2].doesOccur) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
if(options[ITERATIONS].doesOccur) {
iterations = atoi(options[ITERATIONS].value);
- }
-
- if(options[TIME].doesOccur) {
+ if(options[TIME].doesOccur) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ } else if(options[TIME].doesOccur) {
time = atoi(options[TIME].value);
+ } else {
+ iterations = 1000; // some default
}
-
+
if(options[LINE_MODE].doesOccur) {
line_mode = TRUE;
bulk_mode = FALSE;
}
if(options[LOCALE].doesOccur) {
- locale = options[LOCALE].value;
- }
-
- if(time > 0 && iterations >0){
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return;
+ locale = options[LOCALE].value;
}
int32_t len = 0;
- resolvedFileName = NULL;
if(fileName!=NULL){
//pre-flight
ucbuf_resolveFileName(sourceDir, fileName, NULL, &len, &status);
}
ULine* UPerfTest::getLines(UErrorCode& status){
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (lines != NULL) {
+ return lines; // don't do it again
+ }
lines = new ULine[MAXLINES];
int maxLines = MAXLINES;
numLines=0;
return lines;
}
const UChar* UPerfTest::getBuffer(int32_t& len, UErrorCode& status){
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
len = ucbuf_size(ucharBuf);
buffer = (UChar*) uprv_malloc(U_SIZEOF_UCHAR * (len+1));
u_strncpy(buffer,ucbuf_getBuffer(ucharBuf,&bufferLen,&status),len);
}
// call individual tests, to be overriden to call implementations
-UPerfFunction* UPerfTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
+UPerfFunction* UPerfTest::runIndexedTest( int32_t /*index*/, UBool /*exec*/, const char* & /*name*/, char* /*par*/ )
{
// to be overriden by a method like:
/*
}
*/
fprintf(stderr,"*** runIndexedTest needs to be overriden! ***");
- name = ""; exec = exec; index = index; par = par;
return NULL;
}
int32_t loops = 0;
double t=0;
int32_t n = 1;
+ long ops;
do {
this->runIndexedTest( index, FALSE, name );
if (!name || (name[0] == 0))
fprintf(stderr,"%s function returned NULL", name);
return FALSE;
}
- if (testFunction->getOperationsPerIteration() < 1) {
+ ops = testFunction->getOperationsPerIteration();
+ if (ops < 1) {
fprintf(stderr, "%s returned an illegal operations/iteration()\n", name);
return FALSE;
}
loops = iterations;
}
+ double min_t=1000000.0, sum_t=0.0;
+ long events = -1;
+
for(int32_t ps =0; ps < passes; ps++){
- long events = -1;
fprintf(stdout,"= %s begin " ,name);
if(verbose==TRUE){
if(iterations > 0) {
printf("Performance test failed with error: %s \n", u_errorName(status));
break;
}
+ sum_t+=t;
+ if(t<min_t) {
+ min_t=t;
+ }
events = testFunction->getEventsPerIteration();
//print info only in verbose mode
if(verbose==TRUE){
-/*
- if(events == -1){
- fprintf(stdout,"= %s end %f %i %i\n",name , t , loops, testFunction->getOperationsPerIteration());
- }else{
- fprintf(stdout,"= %s end %f %i %i %i\n",name , t , loops, testFunction->getOperationsPerIteration(), events);
- }
-*/
if(events == -1){
- fprintf(stdout, "= %s end: %f loops: %i operations: %li \n", name, t, (int)loops, testFunction->getOperationsPerIteration());
+ fprintf(stdout, "= %s end: %f loops: %i operations: %li \n", name, t, (int)loops, ops);
}else{
- fprintf(stdout, "= %s end: %f loops: %i operations: %li events: %li\n", name, t, (int)loops, testFunction->getOperationsPerIteration(), events);
+ fprintf(stdout, "= %s end: %f loops: %i operations: %li events: %li\n", name, t, (int)loops, ops, events);
}
}else{
-/*
- if(events == -1){
- fprintf(stdout,"= %f %i %i \n", t , loops, testFunction->getOperationsPerIteration());
- }else{
- fprintf(stdout,"= %f %i %i %i\n", t , loops, testFunction->getOperationsPerIteration(), events);
- }
-*/
if(events == -1){
- fprintf(stdout,"= %s end %f %i %li\n", name, t, (int)loops, testFunction->getOperationsPerIteration());
+ fprintf(stdout,"= %s end %f %i %li\n", name, t, (int)loops, ops);
}else{
- fprintf(stdout,"= %s end %f %i %li %li\n", name, t, (int)loops, testFunction->getOperationsPerIteration(), events);
+ fprintf(stdout,"= %s end %f %i %li %li\n", name, t, (int)loops, ops, events);
}
}
}
+ if(verbose && U_SUCCESS(status)) {
+ double avg_t = sum_t/passes;
+ if (loops == 0 || ops == 0) {
+ fprintf(stderr, "%s did not run\n", name);
+ }
+ else if(events == -1) {
+ fprintf(stdout, "%%= %s avg: %.4g loops: %i avg/op: %.4g ns\n",
+ name, avg_t, (int)loops, (avg_t*1E9)/(loops*ops));
+ fprintf(stdout, "_= %s min: %.4g loops: %i min/op: %.4g ns\n",
+ name, min_t, (int)loops, (min_t*1E9)/(loops*ops));
+ }
+ else {
+ fprintf(stdout, "%%= %s avg: %.4g loops: %i avg/op: %.4g ns avg/event: %.4g ns\n",
+ name, avg_t, (int)loops, (avg_t*1E9)/(loops*ops), (avg_t*1E9)/(loops*events));
+ fprintf(stdout, "_= %s min: %.4g loops: %i min/op: %.4g ns min/event: %.4g ns\n",
+ name, min_t, (int)loops, (min_t*1E9)/(loops*ops), (min_t*1E9)/(loops*events));
+ }
+ }
delete testFunction;
}
index++;
*/
void UPerfTest::usage( void )
{
+ puts(gUsageString);
+ if (_addUsage != NULL) {
+ puts(_addUsage);
+ }
+
UBool save_verbose = verbose;
verbose = TRUE;
fprintf(stdout,"Test names:\n");
this->runIndexedTest( index, FALSE, name );
if (!name)
break;
- fprintf(stdout,name);
- fprintf(stdout,"\n");
+ fprintf(stdout, "%s\n", name);
index++;
}while (name && (name[0] != 0));
verbose = save_verbose;