1 /********************************************************************
3 * Copyright (c) 2002-2004, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
9 static const char delim
= '/';
10 static int32_t execCount
= 0;
11 UPerfTest
* UPerfTest::gTest
= NULL
;
12 static const int MAXLINES
= 40000;
13 const char UPerfTest::gUsageString
[] =
14 "Usage: %s [OPTIONS] [FILES]\n"
15 "\tReads the input file and prints out time taken in seconds\n"
17 "\t-h or -? or --help this usage text\n"
18 "\t-v or --verbose print extra information when processing files\n"
19 "\t-s or --sourcedir source directory for files followed by path\n"
20 "\t followed by path\n"
21 "\t-e or --encoding encoding of source files\n"
22 "\t-u or --uselen perform timing analysis on non-null terminated buffer using length\n"
23 "\t-f or --file-name file to be used as input data\n"
24 "\t-p or --passes Number of passes to be performed. Requires Numeric argument. Cannot be used with --time\n"
25 "\t-i or --iterations Number of iterations to be performed. Requires Numeric argument\n"
26 "\t-t or --time Threshold time for looping until in seconds. Requires Numeric argument.Cannot be used with --iterations\n"
27 "\t-l or --line-mode The data file should be processed in line mode\n"
28 "\t-b or --bulk-mode The data file should be processed in file based. Cannot be used with --line-mode\n"
29 "\t-L or --locale Locale for the test\n";
49 static UOption options
[]={
51 UOPTION_HELP_QUESTION_MARK
,
55 UOPTION_DEF( "uselen", 'u', UOPT_NO_ARG
),
56 UOPTION_DEF( "file-name", 'f', UOPT_REQUIRES_ARG
),
57 UOPTION_DEF( "passes", 'p', UOPT_REQUIRES_ARG
),
58 UOPTION_DEF( "iterations", 'i', UOPT_REQUIRES_ARG
),
59 UOPTION_DEF( "time", 't', UOPT_REQUIRES_ARG
),
60 UOPTION_DEF( "line-mode", 'l', UOPT_NO_ARG
),
61 UOPTION_DEF( "bulk-mode", 'b', UOPT_NO_ARG
),
62 UOPTION_DEF( "locale", 'L', UOPT_REQUIRES_ARG
)
65 UPerfTest::UPerfTest(int32_t argc
, const char* argv
[], UErrorCode
& status
){
81 passes
= iterations
= time
= 0;
84 //initialize the argument list
85 U_MAIN_INIT_ARGS(argc
, argv
);
87 _remainingArgc
= u_parseArgs(argc
, (char**)argv
, (int32_t)(sizeof(options
)/sizeof(options
[0])), options
);
89 // Now setup the arguments
90 if(argc
==1 || options
[HELP1
].doesOccur
|| options
[HELP2
].doesOccur
) {
91 status
= U_ILLEGAL_ARGUMENT_ERROR
;
95 if(options
[VERBOSE
].doesOccur
) {
99 if(options
[SOURCEDIR
].doesOccur
) {
100 sourceDir
= options
[SOURCEDIR
].value
;
103 if(options
[ENCODING
].doesOccur
) {
104 encoding
= options
[ENCODING
].value
;
107 if(options
[USELEN
].doesOccur
) {
111 if(options
[FILE_NAME
].doesOccur
){
112 fileName
= options
[FILE_NAME
].value
;
115 if(options
[PASSES
].doesOccur
) {
116 passes
= atoi(options
[PASSES
].value
);
118 if(options
[ITERATIONS
].doesOccur
) {
119 iterations
= atoi(options
[ITERATIONS
].value
);
122 if(options
[TIME
].doesOccur
) {
123 time
= atoi(options
[TIME
].value
);
126 if(options
[LINE_MODE
].doesOccur
) {
131 if(options
[BULK_MODE
].doesOccur
) {
136 if(options
[LOCALE
].doesOccur
) {
137 locale
= options
[LOCALE
].value
;
140 if(time
> 0 && iterations
>0){
141 status
= U_ILLEGAL_ARGUMENT_ERROR
;
146 resolvedFileName
= NULL
;
149 ucbuf_resolveFileName(sourceDir
, fileName
,resolvedFileName
,&len
, &status
);
150 resolvedFileName
= (char*) uprv_malloc(len
);
152 status
= U_MEMORY_ALLOCATION_ERROR
;
155 if(status
== U_BUFFER_OVERFLOW_ERROR
){
156 status
= U_ZERO_ERROR
;
158 ucbuf_resolveFileName(sourceDir
, fileName
, resolvedFileName
, &len
, &status
);
159 ucharBuf
= ucbuf_open(resolvedFileName
,&encoding
,TRUE
,FALSE
,&status
);
161 if(U_FAILURE(status
)){
162 printf("Could not open the input file %s. Error: %s\n", fileName
, u_errorName(status
));
168 ULine
* UPerfTest::getLines(UErrorCode
& status
){
169 lines
= new ULine
[MAXLINES
];
170 int maxLines
= MAXLINES
;
172 const UChar
* line
=NULL
;
175 line
= ucbuf_readline(ucharBuf
,&len
,&status
);
176 if(line
== NULL
|| U_FAILURE(status
)){
179 lines
[numLines
].name
= new UChar
[len
];
180 lines
[numLines
].len
= len
;
181 memcpy(lines
[numLines
].name
, line
, len
* U_SIZEOF_UCHAR
);
185 if (numLines
>= maxLines
) {
186 maxLines
+= MAXLINES
;
187 ULine
*newLines
= new ULine
[maxLines
];
188 if(newLines
== NULL
) {
189 fprintf(stderr
, "Out of memory reading line %d.\n", (int)numLines
);
190 status
= U_MEMORY_ALLOCATION_ERROR
;
195 memcpy(newLines
, lines
, numLines
*sizeof(ULine
));
202 const UChar
* UPerfTest::getBuffer(int32_t& len
, UErrorCode
& status
){
203 len
= ucbuf_size(ucharBuf
);
204 buffer
= (UChar
*) uprv_malloc(U_SIZEOF_UCHAR
* (len
+1));
205 u_strncpy(buffer
,ucbuf_getBuffer(ucharBuf
,&bufferLen
,&status
),len
);
210 UBool
UPerfTest::run(){
211 if(_remainingArgc
==1){
212 // Testing all methods
216 // Test only the specified fucntion
217 for (int i
= 1; i
< _remainingArgc
; ++i
) {
218 if (_argv
[i
][0] != '-') {
219 char* name
= (char*) _argv
[i
];
221 //fprintf(stdout, "\n=== Handling test: %s: ===\n", name);
222 //fprintf(stdout, "\n%s:\n", name);
224 char* parameter
= strchr( name
, '@' );
230 res
= runTest( name
, parameter
);
231 if (!res
|| (execCount
<= 0)) {
232 fprintf(stdout
, "\n---ERROR: Test doesn't exist: %s!\n", name
);
239 UBool
UPerfTest::runTest(char* name
, char* par
){
244 pos
= strchr( name
, delim
); // check if name contains path (by looking for '/')
246 path
= pos
+1; // store subpath for calling subtest
247 *pos
= 0; // split into two strings
252 if (!name
|| (name
[0] == 0) || (strcmp(name
, "*") == 0)) {
253 rval
= runTestLoop( NULL
, NULL
);
255 }else if (strcmp( name
, "LIST" ) == 0) {
260 rval
= runTestLoop( name
, par
);
264 *pos
= delim
; // restore original value at pos
269 void UPerfTest::setPath( char* pathVal
)
271 this->path
= pathVal
;
274 // call individual tests, to be overriden to call implementations
275 UPerfFunction
* UPerfTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* par
)
277 // to be overriden by a method like:
280 case 0: name = "First Test"; if (exec) FirstTest( par ); break;
281 case 1: name = "Second Test"; if (exec) SecondTest( par ); break;
282 default: name = ""; break;
285 fprintf(stderr
,"*** runIndexedTest needs to be overriden! ***");
286 name
= ""; exec
= exec
; index
= index
; par
= par
;
291 UBool
UPerfTest::runTestLoop( char* testname
, char* par
)
297 UErrorCode status
= U_ZERO_ERROR
;
298 UPerfTest
* saveTest
= gTest
;
304 this->runIndexedTest( index
, FALSE
, name
);
305 if (!name
|| (name
[0] == 0))
308 run_this_test
= TRUE
;
310 run_this_test
= (UBool
) (strcmp( name
, testname
) == 0);
313 UPerfFunction
* testFunction
= this->runIndexedTest( index
, TRUE
, name
, par
);
316 if(testFunction
==NULL
){
317 fprintf(stderr
,"%s function returned NULL", name
);
320 if (testFunction
->getOperationsPerIteration() < 1) {
321 fprintf(stderr
, "%s returned an illegal operations/iteration()\n", name
);
324 if(iterations
== 0) {
326 // Run for specified duration in seconds
328 fprintf(stdout
,"= %s calibrating %i seconds \n", name
, (int)n
);
331 //n *= 1000; // s => ms
332 //System.out.println("# " + meth.getName() + " " + n + " sec");
333 int32_t failsafe
= 1; // last resort for very fast methods
335 while (t
< (int)(n
* 0.9)) { // 90% is close enough
336 if (loops
== 0 || t
== 0) {
340 //System.out.println("# " + meth.getName() + " x " + loops + " = " + t);
341 loops
= (int)((double)n
/ t
* loops
+ 0.5);
343 fprintf(stderr
,"Unable to converge on desired duration");
347 //System.out.println("# " + meth.getName() + " x " + loops);
348 t
= testFunction
->time(loops
,&status
);
349 if(U_FAILURE(status
)){
350 printf("Performance test failed with error: %s \n", u_errorName(status
));
358 for(int32_t ps
=0; ps
< passes
; ps
++){
360 fprintf(stdout
,"= %s begin " ,name
);
363 fprintf(stdout
, "%i\n", (int)loops
);
365 fprintf(stdout
, "%i\n", (int)n
);
368 fprintf(stdout
, "\n");
370 t
= testFunction
->time(loops
, &status
);
371 if(U_FAILURE(status
)){
372 printf("Performance test failed with error: %s \n", u_errorName(status
));
375 events
= testFunction
->getEventsPerIteration();
376 //print info only in verbose mode
380 fprintf(stdout,"= %s end %f %i %i\n",name , t , loops, testFunction->getOperationsPerIteration());
382 fprintf(stdout,"= %s end %f %i %i %i\n",name , t , loops, testFunction->getOperationsPerIteration(), events);
386 fprintf(stdout
, "= %s end: %f loops: %i operations: %li \n", name
, t
, (int)loops
, testFunction
->getOperationsPerIteration());
388 fprintf(stdout
, "= %s end: %f loops: %i operations: %li events: %li\n", name
, t
, (int)loops
, testFunction
->getOperationsPerIteration(), events
);
393 fprintf(stdout,"= %f %i %i \n", t , loops, testFunction->getOperationsPerIteration());
395 fprintf(stdout,"= %f %i %i %i\n", t , loops, testFunction->getOperationsPerIteration(), events);
399 fprintf(stdout
,"= %s end %f %i %li\n", name
, t
, (int)loops
, testFunction
->getOperationsPerIteration());
401 fprintf(stdout
,"= %s end %f %i %li %li\n", name
, t
, (int)loops
, testFunction
->getOperationsPerIteration(), events
);
415 * Print a usage message for this test class.
417 void UPerfTest::usage( void )
419 UBool save_verbose
= verbose
;
421 fprintf(stdout
,"Test names:\n");
422 fprintf(stdout
,"-----------\n");
425 const char* name
= NULL
;
427 this->runIndexedTest( index
, FALSE
, name
);
430 fprintf(stdout
,name
);
431 fprintf(stdout
,"\n");
433 }while (name
&& (name
[0] != 0));
434 verbose
= save_verbose
;
440 void UPerfTest::setCaller( UPerfTest
* callingTest
)
442 caller
= callingTest
;
444 verbose
= caller
->verbose
;
448 UBool
UPerfTest::callTest( UPerfTest
& testToBeCalled
, char* par
)
450 execCount
--; // correct a previously assumed test-exec, as this only calls a subtest
451 testToBeCalled
.setCaller( this );
452 return testToBeCalled
.runTest( path
, par
);
455 UPerfTest::~UPerfTest(){
462 ucbuf_close(ucharBuf
);