1/* 2 ********************************************************************** 3 * Copyright (C) 2002-2008, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 * file name: utrie2perf.cpp 7 * encoding: US-ASCII 8 * tab size: 8 (not used) 9 * indentation:4 10 * 11 * created on: 2008sep07 12 * created by: Markus W. Scherer 13 * 14 * Performance test program for UTrie2. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include "unicode/uchar.h" 20#include "unicode/unorm.h" 21#include "unicode/uperf.h" 22#include "uoptions.h" 23 24#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 25 26#if 0 27// Left over from when icu/branches/markus/utf8 could use both old UTrie 28// and new UTrie2, switched with #if in unorm.cpp and ubidi_props.c. 29// Comparative benchmarks were done in that branch on revision r24630 30// and earlier. 31U_CAPI void U_EXPORT2 32unorm_initUTrie2(UErrorCode *pErrorCode); 33 34U_CAPI void U_EXPORT2 35ubidi_initUTrie2(UErrorCode *pErrorCode); 36#endif 37 38U_NAMESPACE_BEGIN 39 40class UnicodeSet; 41 42U_NAMESPACE_END 43 44// Test object. 45class UTrie2PerfTest : public UPerfTest { 46public: 47 UTrie2PerfTest(int32_t argc, const char *argv[], UErrorCode &status) 48 : UPerfTest(argc, argv, NULL, 0, "", status), 49 utf8(NULL), utf8Length(0), countInputCodePoints(0) { 50 if (U_SUCCESS(status)) { 51#if 0 // See comment at unorm_initUTrie2() forward declaration. 52 unorm_initUTrie2(&status); 53 ubidi_initUTrie2(&status); 54#endif 55 int32_t inputLength; 56 UPerfTest::getBuffer(inputLength, status); 57 if(U_SUCCESS(status) && inputLength>0) { 58 countInputCodePoints = u_countChar32(buffer, bufferLen); 59 60 // Preflight the UTF-8 length and allocate utf8. 61 u_strToUTF8(NULL, 0, &utf8Length, buffer, bufferLen, &status); 62 if(status==U_BUFFER_OVERFLOW_ERROR) { 63 utf8=(char *)malloc(utf8Length); 64 if(utf8!=NULL) { 65 status=U_ZERO_ERROR; 66 u_strToUTF8(utf8, utf8Length, NULL, buffer, bufferLen, &status); 67 } else { 68 status=U_MEMORY_ALLOCATION_ERROR; 69 } 70 } 71 72 if(verbose) { 73 printf("code points:%ld len16:%ld len8:%ld " 74 "B/cp:%.3g\n", 75 (long)countInputCodePoints, (long)bufferLen, (long)utf8Length, 76 (double)utf8Length/countInputCodePoints); 77 } 78 } 79 } 80 } 81 82 virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec, const char* &name, char* par = NULL); 83 84 const UChar *getBuffer() const { return buffer; } 85 int32_t getBufferLen() const { return bufferLen; } 86 87 char *utf8; 88 int32_t utf8Length; 89 90 // Number of code points in the input text. 91 int32_t countInputCodePoints; 92}; 93 94// Performance test function object. 95class Command : public UPerfFunction { 96protected: 97 Command(const UTrie2PerfTest &testcase) : testcase(testcase) {} 98 99public: 100 virtual ~Command() {} 101 102 // virtual void call(UErrorCode* pErrorCode) { ... } 103 104 virtual long getOperationsPerIteration() { 105 // Number of code points tested. 106 return testcase.countInputCodePoints; 107 } 108 109 // virtual long getEventsPerIteration(); 110 111 const UTrie2PerfTest &testcase; 112 UNormalizationCheckResult qcResult; 113}; 114 115class CheckFCD : public Command { 116protected: 117 CheckFCD(const UTrie2PerfTest &testcase) : Command(testcase) {} 118public: 119 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 120 return new CheckFCD(testcase); 121 } 122 virtual void call(UErrorCode* pErrorCode) { 123 UErrorCode errorCode=U_ZERO_ERROR; 124 qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(), 125 UNORM_FCD, &errorCode); 126 if(U_FAILURE(errorCode)) { 127 fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n", 128 u_errorName(errorCode)); 129 } 130 } 131}; 132 133#if 0 // See comment at unorm_initUTrie2() forward declaration. 134 135class CheckFCDAlwaysGet : public Command { 136protected: 137 CheckFCDAlwaysGet(const UTrie2PerfTest &testcase) : Command(testcase) {} 138public: 139 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 140 return new CheckFCDAlwaysGet(testcase); 141 } 142 virtual void call(UErrorCode* pErrorCode) { 143 UErrorCode errorCode=U_ZERO_ERROR; 144 qcResult=unorm_quickCheck(testcase.getBuffer(), testcase.getBufferLen(), 145 UNORM_FCD_ALWAYS_GET, &errorCode); 146 if(U_FAILURE(errorCode)) { 147 fprintf(stderr, "error: unorm_quickCheck(UNORM_FCD) failed: %s\n", 148 u_errorName(errorCode)); 149 } 150 } 151}; 152 153U_CAPI UBool U_EXPORT2 154unorm_checkFCDUTF8(const uint8_t *src, int32_t srcLength, const UnicodeSet *nx); 155 156class CheckFCDUTF8 : public Command { 157protected: 158 CheckFCDUTF8(const UTrie2PerfTest &testcase) : Command(testcase) {} 159public: 160 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 161 return new CheckFCDUTF8(testcase); 162 } 163 virtual void call(UErrorCode* pErrorCode) { 164 UBool isFCD=unorm_checkFCDUTF8((const uint8_t *)testcase.utf8, testcase.utf8Length, NULL); 165 if(isFCD>1) { 166 fprintf(stderr, "error: bogus result from unorm_checkFCDUTF8()\n"); 167 } 168 } 169}; 170 171#endif 172 173class ToNFC : public Command { 174protected: 175 ToNFC(const UTrie2PerfTest &testcase) : Command(testcase) { 176 UErrorCode errorCode=U_ZERO_ERROR; 177 destCapacity=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(), 178 UNORM_NFC, 0, 179 NULL, 0, 180 &errorCode); 181 dest=new UChar[destCapacity]; 182 } 183 ~ToNFC() { 184 delete [] dest; 185 } 186public: 187 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 188 return new ToNFC(testcase); 189 } 190 virtual void call(UErrorCode* pErrorCode) { 191 UErrorCode errorCode=U_ZERO_ERROR; 192 int32_t destLength=unorm_normalize(testcase.getBuffer(), testcase.getBufferLen(), 193 UNORM_NFC, 0, 194 dest, destCapacity, 195 &errorCode); 196 if(U_FAILURE(errorCode) || destLength!=destCapacity) { 197 fprintf(stderr, "error: unorm_normalize(UNORM_NFC) failed: %s\n", 198 u_errorName(errorCode)); 199 } 200 } 201 202private: 203 UChar *dest; 204 int32_t destCapacity; 205}; 206 207class GetBiDiClass : public Command { 208protected: 209 GetBiDiClass(const UTrie2PerfTest &testcase) : Command(testcase) {} 210public: 211 static UPerfFunction* get(const UTrie2PerfTest &testcase) { 212 return new GetBiDiClass(testcase); 213 } 214 virtual void call(UErrorCode* pErrorCode) { 215 const UChar *buffer=testcase.getBuffer(); 216 int32_t length=testcase.getBufferLen(); 217 UChar32 c; 218 int32_t i; 219 uint32_t bitSet=0; 220 for(i=0; i<length;) { 221 U16_NEXT(buffer, i, length, c); 222 bitSet|=(uint32_t)1<<u_charDirection(c); 223 } 224 if(length>0 && bitSet==0) { 225 fprintf(stderr, "error: GetBiDiClass() did not collect bits\n"); 226 } 227 } 228}; 229 230UPerfFunction* UTrie2PerfTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* par) { 231 switch (index) { 232 case 0: name = "CheckFCD"; if (exec) return CheckFCD::get(*this); break; 233 case 1: name = "ToNFC"; if (exec) return ToNFC::get(*this); break; 234 case 2: name = "GetBiDiClass"; if (exec) return GetBiDiClass::get(*this); break; 235#if 0 // See comment at unorm_initUTrie2() forward declaration. 236 case 3: name = "CheckFCDAlwaysGet"; if (exec) return CheckFCDAlwaysGet::get(*this); break; 237 case 4: name = "CheckFCDUTF8"; if (exec) return CheckFCDUTF8::get(*this); break; 238#endif 239 default: name = ""; break; 240 } 241 return NULL; 242} 243 244int main(int argc, const char *argv[]) { 245 UErrorCode status = U_ZERO_ERROR; 246 UTrie2PerfTest test(argc, argv, status); 247 248 if (U_FAILURE(status)){ 249 printf("The error is %s\n", u_errorName(status)); 250 test.usage(); 251 return status; 252 } 253 254 if (test.run() == FALSE){ 255 fprintf(stderr, "FAILED: Tests could not be run please check the " 256 "arguments.\n"); 257 return -1; 258 } 259 260 return 0; 261} 262