]> granicus.if.org Git - icu/commitdiff
ICU-13634 Porting some minor ICU4C performance enhancements to Java.
authorShane Carr <shane@unicode.org>
Sat, 21 Apr 2018 08:55:58 +0000 (08:55 +0000)
committerShane Carr <shane@unicode.org>
Sat, 21 Apr 2018 08:55:58 +0000 (08:55 +0000)
X-SVN-Rev: 41259

icu4c/source/i18n/numparse_currency.cpp
icu4c/source/i18n/numparse_currency.h
icu4j/main/classes/core/src/com/ibm/icu/impl/number/parse/CombinedCurrencyMatcher.java
icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java

index 80ec4e7433063558d5130ae542716e4658ed33e0..7b59885072d6e98cb5e2191ce89c5aad7bc3b2f5 100644 (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;
     }
index fa7d67b9bde8ac89e4f89840cd852e7ee4076411..63007451af8216d1ffa559b45050762037a468cf 100644 (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;
index ee303092b3320ea9e4035bfa677d3227f16d9ac0..b4a1caa1c8f334ab8536714d70aef102480f2b77 100644 (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
index 38a89e18b589e8a6c4be6909562e0e505fcafd5f..1800efc47a4c77aa069494a15df4c0831f8986cb 100644 (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;
   }
 
   /**