ICU-13634 Porting some minor ICU4C performance enhancements to Java.

X-SVN-Rev: 41259
This commit is contained in:
Shane Carr 2018-04-21 08:55:58 +00:00
parent e59eb48314
commit be466ddec0
4 changed files with 52 additions and 26 deletions

View File

@ -30,6 +30,8 @@ CombinedCurrencyMatcher::CombinedCurrencyMatcher(const CurrencySymbols& currency
utils::copyCurrencyCode(fCurrencyCode, currencySymbols.getIsoCode());
// TODO: Figure out how to make this faster and re-enable.
// Computing the "lead code points" set for fastpathing is too slow to use in production.
// See http://bugs.icu-project.org/trac/ticket/13584
// // Compute the full set of characters that could be the first in a currency to allow for
// // efficient smoke test.
// fLeadCodePoints.add(fCurrency1.char32At(0));
@ -41,8 +43,8 @@ CombinedCurrencyMatcher::CombinedCurrencyMatcher(const CurrencySymbols& currency
// fLeadCodePoints.freeze();
}
bool CombinedCurrencyMatcher::match(StringSegment& segment, ParsedNumber& result,
UErrorCode& status) const {
bool
CombinedCurrencyMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const {
if (result.currencyCode[0] != 0) {
return false;
}

View File

@ -53,7 +53,8 @@ class CombinedCurrencyMatcher : public NumberParseMatcher, public UMemory {
// Locale has a non-trivial default constructor.
CharString fLocaleName;
UnicodeSet fLeadCodePoints;
// TODO: See comments in constructor in numparse_currency.cpp
// UnicodeSet fLeadCodePoints;
/** Matches the currency string without concern for currency spacing. */
bool matchCurrency(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const;

View File

@ -7,7 +7,6 @@ import java.util.Iterator;
import com.ibm.icu.impl.StringSegment;
import com.ibm.icu.impl.TextTrieMap;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.Currency.CurrencyStringInfo;
@ -34,7 +33,8 @@ public class CombinedCurrencyMatcher implements NumberParseMatcher {
private final TextTrieMap<CurrencyStringInfo> longNameTrie;
private final TextTrieMap<CurrencyStringInfo> symbolTrie;
private final UnicodeSet leadCodePoints;
// TODO: See comments in constructor.
// private final UnicodeSet leadCodePoints;
public static CombinedCurrencyMatcher getInstance(Currency currency, DecimalFormatSymbols dfs) {
// TODO: Cache these instances. They are somewhat expensive.
@ -46,27 +46,30 @@ public class CombinedCurrencyMatcher implements NumberParseMatcher {
this.currency1 = currency.getSymbol(dfs.getULocale());
this.currency2 = currency.getCurrencyCode();
afterPrefixInsert = dfs
.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT, false);
beforeSuffixInsert = dfs
.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT, true);
afterPrefixInsert = dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT,
false);
beforeSuffixInsert = dfs.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT,
true);
// TODO: Currency trie does not currently have an option for case folding. It defaults to use
// case folding on long-names but not symbols.
longNameTrie = Currency.getParsingTrie(dfs.getULocale(), Currency.LONG_NAME);
symbolTrie = Currency.getParsingTrie(dfs.getULocale(), Currency.SYMBOL_NAME);
// Compute the full set of characters that could be the first in a currency to allow for
// efficient smoke test.
leadCodePoints = new UnicodeSet();
leadCodePoints.add(currency1.codePointAt(0));
leadCodePoints.add(currency2.codePointAt(0));
leadCodePoints.add(beforeSuffixInsert.codePointAt(0));
longNameTrie.putLeadCodePoints(leadCodePoints);
symbolTrie.putLeadCodePoints(leadCodePoints);
// Always apply case mapping closure for currencies
leadCodePoints.closeOver(UnicodeSet.ADD_CASE_MAPPINGS);
leadCodePoints.freeze();
// TODO: Figure out how to make this faster and re-enable.
// Computing the "lead code points" set for fastpathing is too slow to use in production.
// See http://bugs.icu-project.org/trac/ticket/13584
// // Compute the full set of characters that could be the first in a currency to allow for
// // efficient smoke test.
// leadCodePoints = new UnicodeSet();
// leadCodePoints.add(currency1.codePointAt(0));
// leadCodePoints.add(currency2.codePointAt(0));
// leadCodePoints.add(beforeSuffixInsert.codePointAt(0));
// longNameTrie.putLeadCodePoints(leadCodePoints);
// symbolTrie.putLeadCodePoints(leadCodePoints);
// // Always apply case mapping closure for currencies
// leadCodePoints.closeOver(UnicodeSet.ADD_CASE_MAPPINGS);
// leadCodePoints.freeze();
}
@Override
@ -141,7 +144,9 @@ public class CombinedCurrencyMatcher implements NumberParseMatcher {
@Override
public boolean smokeTest(StringSegment segment) {
return segment.startsWith(leadCodePoints);
// TODO: See constructor
return true;
// return segment.startsWith(leadCodePoints);
}
@Override

View File

@ -289,7 +289,7 @@ public class DecimalFormat extends NumberFormat {
transient volatile DecimalFormatProperties exportedProperties;
transient volatile NumberParserImpl parser;
transient volatile NumberParserImpl parserWithCurrency;
transient volatile NumberParserImpl currencyParser;
//=====================================================================================//
// CONSTRUCTORS //
@ -818,6 +818,7 @@ public class DecimalFormat extends NumberFormat {
// Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
// parseCurrency method (backwards compatibility)
int startIndex = parsePosition.getIndex();
NumberParserImpl parser = getParser();
parser.parse(text, startIndex, true, result);
if (result.success()) {
parsePosition.setIndex(result.charEnd);
@ -857,11 +858,12 @@ public class DecimalFormat extends NumberFormat {
ParsedNumber result = new ParsedNumber();
int startIndex = parsePosition.getIndex();
parserWithCurrency.parse(text.toString(), startIndex, true, result);
NumberParserImpl parser = getCurrencyParser();
parser.parse(text.toString(), startIndex, true, result);
if (result.success()) {
parsePosition.setIndex(result.charEnd);
// TODO: Accessing properties here is technically not thread-safe
Number number = result.getNumber(parserWithCurrency.getParseFlags());
Number number = result.getNumber(parser.getParseFlags());
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
if (number instanceof java.math.BigDecimal) {
number = safeConvertBigDecimal((java.math.BigDecimal) number);
@ -2503,8 +2505,24 @@ public class DecimalFormat extends NumberFormat {
}
assert locale != null;
formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale);
parser = NumberParserImpl.createParserFromProperties(properties, symbols, false);
parserWithCurrency = NumberParserImpl.createParserFromProperties(properties, symbols, true);
// Lazy-initialize the parsers only when we need them.
parser = null;
currencyParser = null;
}
NumberParserImpl getParser() {
if (parser == null) {
parser = NumberParserImpl.createParserFromProperties(properties, symbols, false);
}
return parser;
}
NumberParserImpl getCurrencyParser() {
if (currencyParser == null) {
currencyParser = NumberParserImpl.createParserFromProperties(properties, symbols, true);
}
return currencyParser;
}
/**