Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7050528

Improve performance of java.text.DecimalFormat.format() call stack

    Details

    • Type: Enhancement
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 7
    • Fix Version/s: 8
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b61
    • CPU:
      generic
    • OS:
      generic

      Backports

        Description

        SpecJEntreprise 2010 uses a lot NumberFormat default usage path (NumberFormat.getInstance() + format(double) method) to report
        data to end-user. This kind of usage is relevant is most business
        JEE server applications as well.

        This in turn translate to using DecimalFormat.format(...) methods
        either for currency or decimal usage. DecimalFormat.format() call
        stack has shown to consume a lot of CPU time in JEnt profiles (from
        16% in 2010 to 6.5% recently (02-2011)). Improving format() call
        stack may bring a lot to SpecJEntreprise or Business server apps.

          Issue Links

            Activity

            Hide
            olagneau Olivier Lagneau added a comment -
            BT2:SUGGESTED FIX

            After trying several possible optimization solutions, one has shown
            to provide best performances. Here is a limited description of this
            optimized algorithm, a fast-path for double values in the Integer range
            used when the DecimalFormat instance used follows a set of constraints
            mostly valid when the defaut instanciation path is used (NumberFormat.get[Currency]Instance() :

            - Verify first that the optimized fast-path can be applied,
              depending on both DecimalFormat instance and passed double value.
            - If optimization cannot be applied, fallback to existing algorithm,
              otherwise :
            - Decompose double value into its integral and fractional part.
            - Decide if rounding must be applied on the passed double value.
            - Collect digit from integral and fractional parts converted into integer,
              taking into accoount rounding and special cases (like all nines, i.e. "99...99,99...",
              using char arrays only and char assignment (no use of either String or StringBuilder).
              Pattern rule and punctuation chars is applied directly while collecting digits.
            - Localize the collected digits (if needed) in the given Locale.
            - Add required prefix and suffix.
            - Build and return a String from the char array used.

            The algorithm can be applied both in currency or non-currency instantiation case.

            The footprint cost of the fast-path algorithm is ~6kbytes of static data
            containinig char array constant to collect digits from integer values,
            plus for each instance a set of utility fields (8) and state fields (12),
            most of which with a basic type, to support the new algorithm.

            This rewriting of DecimalFormat.format() call stack has shown a speedup of
            ~x9 (X86) to ~x11 (SPARC-USIV+) depending on the architecturre, and x10 on T4.

            The micro-benchmark used for testing the perf improvement is single-threaded
            and consists in calling NumberFormat.format(double) on a large set (1000000)
            of double values "fairly" distributed in the integer range. Fairly means that
            the used values do not put the fast-path algorithm in a priviledged situation
            where less work has to done.
            Show
            olagneau Olivier Lagneau added a comment - BT2:SUGGESTED FIX After trying several possible optimization solutions, one has shown to provide best performances. Here is a limited description of this optimized algorithm, a fast-path for double values in the Integer range used when the DecimalFormat instance used follows a set of constraints mostly valid when the defaut instanciation path is used (NumberFormat.get[Currency]Instance() : - Verify first that the optimized fast-path can be applied,   depending on both DecimalFormat instance and passed double value. - If optimization cannot be applied, fallback to existing algorithm,   otherwise : - Decompose double value into its integral and fractional part. - Decide if rounding must be applied on the passed double value. - Collect digit from integral and fractional parts converted into integer,   taking into accoount rounding and special cases (like all nines, i.e. "99...99,99...",   using char arrays only and char assignment (no use of either String or StringBuilder).   Pattern rule and punctuation chars is applied directly while collecting digits. - Localize the collected digits (if needed) in the given Locale. - Add required prefix and suffix. - Build and return a String from the char array used. The algorithm can be applied both in currency or non-currency instantiation case. The footprint cost of the fast-path algorithm is ~6kbytes of static data containinig char array constant to collect digits from integer values, plus for each instance a set of utility fields (8) and state fields (12), most of which with a basic type, to support the new algorithm. This rewriting of DecimalFormat.format() call stack has shown a speedup of ~x9 (X86) to ~x11 (SPARC-USIV+) depending on the architecturre, and x10 on T4. The micro-benchmark used for testing the perf improvement is single-threaded and consists in calling NumberFormat.format(double) on a large set (1000000) of double values "fairly" distributed in the integer range. Fairly means that the used values do not put the fast-path algorithm in a priviledged situation where less work has to done.
            Hide
            olagneau Olivier Lagneau added a comment -
            BT2:EVALUATION

            To provide best performance improvements, one can take advantage of the
            properties of the instances of DecimalFormat that are used by most business
            application, that is properties of instances returned by NumberFormat.getInstance()
            or getCurrencyInstance(). In addition most of these applications will use
            double values that are most of the time in the Integer range.

            The profiling of the call stack of NumberFormat.format(double, ...) shows that
            there are three main time consumers :
            - sun.misc.FloatingDecimal.dtoa(),
            - java.text.DigitList.set(),
            - java.text.DecimalFormat.subformat() private method.
            Thus these time consumers must be avoided

            A rewriting of DecimalFormat().subformat that is specifically designed for
            DecimalFormat instances returned by NumberFormat.get[Currency]Instance() and
            double values in the Integer range should be exercized.
            *** (#1 of 1): [ UNSAVED ] ###@###.###
            Show
            olagneau Olivier Lagneau added a comment - BT2:EVALUATION To provide best performance improvements, one can take advantage of the properties of the instances of DecimalFormat that are used by most business application, that is properties of instances returned by NumberFormat.getInstance() or getCurrencyInstance(). In addition most of these applications will use double values that are most of the time in the Integer range. The profiling of the call stack of NumberFormat.format(double, ...) shows that there are three main time consumers : - sun.misc.FloatingDecimal.dtoa(), - java.text.DigitList.set(), - java.text.DecimalFormat.subformat() private method. Thus these time consumers must be avoided A rewriting of DecimalFormat().subformat that is specifically designed for DecimalFormat instances returned by NumberFormat.get[Currency]Instance() and double values in the Integer range should be exercized. *** (#1 of 1): [ UNSAVED ] ###@###.###
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk8/tl/jdk/rev/75080f572f84
            User: alanb
            Date: 2012-10-02 09:15:18 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk8/tl/jdk/rev/75080f572f84 User: alanb Date: 2012-10-02 09:15:18 +0000

              People

              • Assignee:
                olagneau Olivier Lagneau
                Reporter:
                olagneau Olivier Lagneau
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: