diff options
author | Elliott Hughes <enh@google.com> | 2009-12-21 10:52:53 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2009-12-21 15:02:47 -0800 |
commit | 2e3a41defb42a97b463194d859d2d4088a600fd8 (patch) | |
tree | 67a89bce7f2450e9125b96074e0848a71ab4f451 /icu/src/main/native | |
parent | 011496fc0d73dc55c452eb1d7b60fe3c73885921 (diff) | |
download | libcore-2e3a41defb42a97b463194d859d2d4088a600fd8.zip libcore-2e3a41defb42a97b463194d859d2d4088a600fd8.tar.gz libcore-2e3a41defb42a97b463194d859d2d4088a600fd8.tar.bz2 |
Speed up the way we access ICU's locale data.
This patch makes creating a new NumberFormat or new SimpleDateFormat 2x faster.
Basically, the ResourceBundle mechanism is really expensive in several ways:
1. The two-level caching is unnecessary for locale data, and expensive because
it burns through a lot of temporary objects.
2. The PrivilegedAction stuff is unnecessary and expensive because it too burns
quite a few temporary objects (including an ArrayList for each call; should
we consider removing support for SecurityManager so we can remove this cruft
from our code?).
3. The caching in most cases doesn't cache anything useful; the ResourceBundles
simply forward all questions straight to native code anyway, all we're
caching is an unnecessary forwarding object (in a cache where lookups cost
more than just creating a new unnecessary forwarding object would cost).
I've left CurrencyResourceBundle on the slow (ResourceBundle.getBundle) path
because I'm not yet sure how much of that path's semantics it relies on.
I still return LocaleResourceBundle instances (albeit via a much faster path)
but we should fix that. The native code returns an array which ResourceBundle
stuffs into a Hashtable and the calling code accesses via hash table lookups.
This despite the fact that the keys are a small fixed set known in advance.
We could make the native layer and the calling layer simpler and faster by
using a "struct", and doing so would make the middle layer go away completely.
Diffstat (limited to 'icu/src/main/native')
-rw-r--r-- | icu/src/main/native/ResourceInterface.cpp | 234 |
1 files changed, 61 insertions, 173 deletions
diff --git a/icu/src/main/native/ResourceInterface.cpp b/icu/src/main/native/ResourceInterface.cpp index 731cf3f..243d7c4 100644 --- a/icu/src/main/native/ResourceInterface.cpp +++ b/icu/src/main/native/ResourceInterface.cpp @@ -54,9 +54,9 @@ static jstring getJStringFromUnicodeString(JNIEnv *env, UnicodeString string) { int stringLength = string.length(); jchar *res = (jchar *) malloc(sizeof(jchar) * (stringLength + 1)); string.extract(res, stringLength+1, status); - if(U_FAILURE(status)) { + if (U_FAILURE(status)) { free(res); - LOGI("Error getting string for getJStringFromUnicodeString"); + LOGE("Error getting string for getJStringFromUnicodeString: %s", u_errorName(status)); status = U_ZERO_ERROR; return NULL; } @@ -76,10 +76,7 @@ static void addObject(JNIEnv *env, jobjectArray result, const char *keyStr, jobj env->DeleteLocalRef(element); } -static jint getFractionDigitsNative(JNIEnv* env, jclass clazz, - jstring currencyCode) { - // LOGI("ENTER getFractionDigitsNative"); - +static jint getCurrencyFractionDigitsNative(JNIEnv* env, jclass clazz, jstring currencyCode) { UErrorCode status = U_ZERO_ERROR; NumberFormat *fmt = NumberFormat::createCurrencyInstance(status); @@ -229,135 +226,77 @@ static jstring getCurrencySymbolNative(JNIEnv* env, jclass clazz, static jstring getDisplayCountryNative(JNIEnv* env, jclass clazz, jstring targetLocale, jstring locale) { - // LOGI("ENTER getDisplayCountryNative"); - - UErrorCode status = U_ZERO_ERROR; Locale loc = getLocale(env, locale); Locale targetLoc = getLocale(env, targetLocale); - + UnicodeString string; targetLoc.getDisplayCountry(loc, string); - - jstring result = getJStringFromUnicodeString(env, string); - - return result; + return getJStringFromUnicodeString(env, string); } static jstring getDisplayLanguageNative(JNIEnv* env, jclass clazz, jstring targetLocale, jstring locale) { - // LOGI("ENTER getDisplayLanguageNative"); Locale loc = getLocale(env, locale); Locale targetLoc = getLocale(env, targetLocale); UnicodeString string; targetLoc.getDisplayLanguage(loc, string); - - jstring result = getJStringFromUnicodeString(env, string); - - return result; + return getJStringFromUnicodeString(env, string); } static jstring getDisplayVariantNative(JNIEnv* env, jclass clazz, jstring targetLocale, jstring locale) { - // LOGI("ENTER getDisplayVariantNative"); Locale loc = getLocale(env, locale); Locale targetLoc = getLocale(env, targetLocale); - + UnicodeString string; targetLoc.getDisplayVariant(loc, string); - - jstring result = getJStringFromUnicodeString(env, string); - - return result; + return getJStringFromUnicodeString(env, string); } static jstring getISO3CountryNative(JNIEnv* env, jclass clazz, jstring locale) { - // LOGI("ENTER getISO3CountryNative"); - Locale loc = getLocale(env, locale); - - const char *string = loc.getISO3Country(); - - jstring result = env->NewStringUTF(string); - - return result; + return env->NewStringUTF(loc.getISO3Country()); } static jstring getISO3LanguageNative(JNIEnv* env, jclass clazz, jstring locale) { - // LOGI("ENTER getISO3LanguageNative"); - Locale loc = getLocale(env, locale); - - const char *string = loc.getISO3Language(); - - jstring result = env->NewStringUTF(string); - - return result; + return env->NewStringUTF(loc.getISO3Language()); } -static jobjectArray getISOCountriesNative(JNIEnv* env, jclass clazz) { - // LOGI("ENTER getISOCountriesNative"); - - const char* const* strings = Locale::getISOCountries(); - - int count = 0; - while(strings[count] != NULL) { - count++; +static jobjectArray toStringArray(JNIEnv* env, const char* const* strings) { + size_t count = 0; + while (strings[count] != NULL) { + ++count; } - jobjectArray result = env->NewObjectArray(count, string_class, NULL); - - jstring res; - for(int i = 0; i < count; i++) { - res = env->NewStringUTF(strings[i]); - env->SetObjectArrayElement(result, i, res); - env->DeleteLocalRef(res); + for (size_t i = 0; i < count; ++i) { + jstring s = env->NewStringUTF(strings[i]); + env->SetObjectArrayElement(result, i, s); + env->DeleteLocalRef(s); } return result; } -static jobjectArray getISOLanguagesNative(JNIEnv* env, jclass clazz) { - // LOGI("ENTER getISOLanguagesNative"); - - const char* const* strings = Locale::getISOLanguages(); - - const char *string = strings[0]; - - int count = 0; - while(strings[count] != NULL) { - count++; - } - - jobjectArray result = env->NewObjectArray(count, string_class, NULL); +static jobjectArray getISOCountriesNative(JNIEnv* env, jclass clazz) { + return toStringArray(env, Locale::getISOCountries()); +} - jstring res; - for(int i = 0; i < count; i++) { - res = env->NewStringUTF(strings[i]); - env->SetObjectArrayElement(result, i, res); - env->DeleteLocalRef(res); - } - return result; +static jobjectArray getISOLanguagesNative(JNIEnv* env, jclass clazz) { + return toStringArray(env, Locale::getISOLanguages()); } static jobjectArray getAvailableLocalesNative(JNIEnv* env, jclass clazz) { - // LOGI("ENTER getAvailableLocalesNative"); - - int count = uloc_countAvailable(); - + size_t count = uloc_countAvailable(); jobjectArray result = env->NewObjectArray(count, string_class, NULL); - - jstring res; - const char * string; - for(int i = 0; i < count; i++) { - string = uloc_getAvailable(i); - res = env->NewStringUTF(string); - env->SetObjectArrayElement(result, i, res); - env->DeleteLocalRef(res); + for (size_t i = 0; i < count; ++i) { + jstring s = env->NewStringUTF(uloc_getAvailable(i)); + env->SetObjectArrayElement(result, i, s); + env->DeleteLocalRef(s); } - return result; } @@ -497,64 +436,53 @@ static jstring getDisplayTimeZoneNative(JNIEnv* env, jclass clazz, return result; } -static void getDayInitVector(JNIEnv *env, UResourceBundle *gregorian, int *values) { - - UErrorCode status = U_ZERO_ERROR; +static void getDayIntVector(JNIEnv *env, UResourceBundle *gregorian, int *values) { // get the First day of week and the minimal days in first week numbers + UErrorCode status = U_ZERO_ERROR; UResourceBundle *gregorianElems = ures_getByKey(gregorian, "DateTimeElements", NULL, &status); - if(U_FAILURE(status)) { + if (U_FAILURE(status)) { return; } int intVectSize; - const int *result; - result = ures_getIntVector(gregorianElems, &intVectSize, &status); - if(U_FAILURE(status)) { + const int* result = ures_getIntVector(gregorianElems, &intVectSize, &status); + if (U_FAILURE(status)) { ures_close(gregorianElems); return; } - - if(intVectSize == 2) { + + if (intVectSize == 2) { values[0] = result[0]; values[1] = result[1]; } ures_close(gregorianElems); - } static jobjectArray getAmPmMarkers(JNIEnv *env, UResourceBundle *gregorian) { - - jobjectArray amPmMarkers; - jstring pmU, amU; - UErrorCode status = U_ZERO_ERROR; - - UResourceBundle *gregorianElems; - - gregorianElems = ures_getByKey(gregorian, "AmPmMarkers", NULL, &status); - if(U_FAILURE(status)) { + UResourceBundle *gregorianElems = ures_getByKey(gregorian, "AmPmMarkers", NULL, &status); + if (U_FAILURE(status)) { return NULL; } - int lengthAm, lengthPm; - ures_resetIterator(gregorianElems); + int lengthAm, lengthPm; const jchar* am = ures_getStringByIndex(gregorianElems, 0, &lengthAm, &status); const jchar* pm = ures_getStringByIndex(gregorianElems, 1, &lengthPm, &status); - if(U_FAILURE(status)) { + if (U_FAILURE(status)) { ures_close(gregorianElems); return NULL; } - amPmMarkers = env->NewObjectArray(2, string_class, NULL); - amU = env->NewString(am, lengthAm); + jobjectArray amPmMarkers = env->NewObjectArray(2, string_class, NULL); + jstring amU = env->NewString(am, lengthAm); env->SetObjectArrayElement(amPmMarkers, 0, amU); env->DeleteLocalRef(amU); - pmU = env->NewString(pm, lengthPm); + jstring pmU = env->NewString(pm, lengthPm); env->SetObjectArrayElement(amPmMarkers, 1, pmU); env->DeleteLocalRef(pmU); ures_close(gregorianElems); @@ -813,41 +741,26 @@ static jobjectArray getShortWeekdayNames(JNIEnv *env, UResourceBundle *gregorian } static jstring getDecimalPatternChars(JNIEnv *env, UResourceBundle *rootElems) { - UErrorCode status = U_ZERO_ERROR; int zeroL, digitL, decSepL, groupL, listL, percentL, permillL, expL, currSepL, minusL; - int patternLength; - - jchar *patternChars; const jchar* zero = ures_getStringByIndex(rootElems, 4, &zeroL, &status); - const jchar* digit = ures_getStringByIndex(rootElems, 5, &digitL, &status); - const jchar* decSep = ures_getStringByIndex(rootElems, 0, &decSepL, &status); - const jchar* group = ures_getStringByIndex(rootElems, 1, &groupL, &status); - const jchar* list = ures_getStringByIndex(rootElems, 2, &listL, &status); - const jchar* percent = ures_getStringByIndex(rootElems, 3, &percentL, &status); - const jchar* permill = ures_getStringByIndex(rootElems, 8, &permillL, &status); - const jchar* exp = ures_getStringByIndex(rootElems, 7, &expL, &status); - const jchar* currSep = ures_getStringByIndex(rootElems, 0, &currSepL, &status); - const jchar* minus = ures_getStringByIndex(rootElems, 6, &minusL, &status); - if(U_FAILURE(status)) { + if (U_FAILURE(status)) { return NULL; } - - patternChars = (jchar *) malloc(11 * sizeof(jchar)); - + jchar patternChars[11]; patternChars[0] = 0; u_strncat(patternChars, zero, 1); @@ -861,11 +774,7 @@ static jstring getDecimalPatternChars(JNIEnv *env, UResourceBundle *rootElems) { u_strncat(patternChars, currSep, 1); u_strncat(patternChars, minus, 1); - jstring decimalPatternChars = env->NewString(patternChars, 10); - - free(patternChars); - - return decimalPatternChars; + return env->NewString(patternChars, 10); } static jstring getIntCurrencyCode(JNIEnv *env, jclass clazz, jstring locale) { @@ -891,32 +800,21 @@ static jstring getIntCurrencyCode(JNIEnv *env, jclass clazz, jstring locale) { } static jstring getCurrencySymbol(JNIEnv *env, jclass clazz, jstring locale, jstring intCurrencySymbol) { - jstring result = getCurrencySymbolNative(env, clazz, locale, intCurrencySymbol); - if(result == intCurrencySymbol) { - return NULL; - } - return result; - + return (result == intCurrencySymbol) ? NULL : result; } -static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, - jstring locale, jboolean needsTZ) { - - UErrorCode status = U_ZERO_ERROR; - +static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, jstring locale) { const char *loc = env->GetStringUTFChars(locale, NULL); - UResourceBundle *root = ures_openU(NULL, loc, &status); - + UErrorCode status = U_ZERO_ERROR; + UResourceBundle* root = ures_openU(NULL, loc, &status); env->ReleaseStringUTFChars(locale, loc); - if(U_FAILURE(status)) { - LOGI("Error getting resources"); + if (U_FAILURE(status)) { + LOGE("Error getting resources: %s", u_errorName(status)); status = U_ZERO_ERROR; return NULL; } - - jclass obj_class = env->FindClass("[Ljava/lang/Object;"); jclass integer_class = env->FindClass("java/lang/Integer"); jmethodID integerInit = env->GetMethodID(integer_class, "<init>", "(I)V"); @@ -952,7 +850,6 @@ static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, int counter = 0; - int firstDayVals[2] = {-1, -1}; const jchar* nan = (const jchar *)NULL; const jchar* inf = (const jchar *)NULL; @@ -981,7 +878,8 @@ static jobjectArray getContentImpl(JNIEnv* env, jclass clazz, // adding the first day of week and minimal days in first week values - getDayInitVector(env, gregorian, firstDayVals); + int firstDayVals[2] = {-1, -1}; + getDayIntVector(env, gregorian, firstDayVals); if((firstDayVals[0] != -1) && (firstDayVals[1] != -1)) { firstDayOfWeek = env->NewObject(integer_class, integerInit, firstDayVals[0]); minimalDaysInFirstWeek = env->NewObject(integer_class, integerInit, firstDayVals[1]); @@ -1254,20 +1152,10 @@ zones: ures_close(root); - if(needsTZ == JNI_TRUE) { - counter++; //add empty timezone - } - - - // collect all content and put it into an array result = env->NewObjectArray(counter, obj_class, NULL); int index = 0; - - if(needsTZ == JNI_TRUE) { - addObject(env, result, "timezones", NULL, index++); - } if(firstDayOfWeek != NULL && index < counter) { addObject(env, result, "First_Day", firstDayOfWeek, index++); } @@ -1353,16 +1241,16 @@ zones: static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ - {"getFractionDigitsNative", "(Ljava/lang/String;)I", - (void*) getFractionDigitsNative}, + {"getCurrencyFractionDigitsNative", "(Ljava/lang/String;)I", + (void*) getCurrencyFractionDigitsNative}, {"getCurrencyCodeNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*) getCurrencyCodeNative}, {"getCurrencySymbolNative", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) getCurrencySymbolNative}, - {"getDisplayCountryNative", + {"getDisplayCountryNative", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) getDisplayCountryNative}, - {"getDisplayLanguageNative", + {"getDisplayLanguageNative", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) getDisplayLanguageNative}, {"getDisplayVariantNative", @@ -1380,14 +1268,14 @@ static JNINativeMethod gMethods[] = { (void*) getISOLanguagesNative}, {"getAvailableLocalesNative", "()[Ljava/lang/String;", (void*) getAvailableLocalesNative}, - {"getTimeZonesNative", + {"getTimeZonesNative", "([[Ljava/lang/String;Ljava/lang/String;)V", (void*) getTimeZonesNative}, - {"getDisplayTimeZoneNative", + {"getDisplayTimeZoneNative", "(Ljava/lang/String;ZILjava/lang/String;)Ljava/lang/String;", (void*) getDisplayTimeZoneNative}, - {"getContentImpl", - "(Ljava/lang/String;Z)[[Ljava/lang/Object;", + {"getContentImpl", + "(Ljava/lang/String;)[[Ljava/lang/Object;", (void*) getContentImpl}, }; |