RFR: 8334328: Reduce object allocation for FloatToDecimal and DoubleToDecimal

Shaojin Wen duke at openjdk.org
Sat Jun 15 04:57:20 UTC 2024


On Sat, 15 Jun 2024 03:02:19 GMT, Chen Liang <liach at openjdk.org> wrote:

>> The current versions of FloatToDecimal and DoubleToDecimal allocate additional objects. Reducing these allocations can improve the performance of Float/Double.toString and AbstractStringBuilder's append(float/double).
>> 
>> This patch is just a code refactoring to reduce object allocation, but does not change the Float/Double to decimal algorithm.
>> 
>> The following code comments the allocated objects to be removed.
>> 
>> 
>> class FloatToDecimal {
>>     public static String toString(float v) {
>>         // allocate object FloatToDecimal
>>         return new FloatToDecimal().toDecimalString(v);
>>     }
>> 
>>     public static Appendable appendTo(float v, Appendable app)
>>             throws IOException {
>>         // allocate object FloatToDecimal
>>         return new FloatToDecimal().appendDecimalTo(v, app);
>>     }
>> 
>>     private Appendable appendDecimalTo(float v, Appendable app)
>>             throws IOException {
>>         switch (toDecimal(v)) {
>>             case NON_SPECIAL:
>>                 // allocate object char[]
>>                 char[] chars = new char[index + 1];
>>                 for (int i = 0; i < chars.length; ++i) {
>>                     chars[i] = (char) bytes[i];
>>                 }
>>                 if (app instanceof StringBuilder builder) {
>>                     return builder.append(chars);
>>                 }
>>                 if (app instanceof StringBuffer buffer) {
>>                     return buffer.append(chars);
>>                 }
>>                 for (char c : chars) {
>>                     app.append(c);
>>                 }
>>                 return app;
>>             // ...
>>         }
>>     }
>> }
>> 
>> class DoubleToDecimal {
>>     public static String toString(double v) {
>>         // allocate object DoubleToDecimal
>>         return new DoubleToDecimal(false).toDecimalString(v);
>>     }
>> 
>>     public static Appendable appendTo(double v, Appendable app)
>>             throws IOException {
>>         // allocate object DoubleToDecimal
>>         return new DoubleToDecimal(false).appendDecimalTo(v, app);
>>     }
>> 
>>     private Appendable appendDecimalTo(double v, Appendable app)
>>             throws IOException {
>>         switch (toDecimal(v, null)) {
>>             case NON_SPECIAL:
>>                 // allocate object char[]
>>                 char[] chars = new char[index + 1];
>>                 for (int i = 0; i < chars.length; ++i) {
>>                     chars[i] = (char) bytes[i];
>>                 }
>>             ...
>
> src/java.base/share/classes/java/lang/AbstractStringBuilder.java line 888:
> 
>> 886:      */
>> 887:     public AbstractStringBuilder append(float f) {
>> 888:         ensureCapacityInternal(count + FloatToDecimal.MAX_CHARS);
> 
> This might cause failure in edge cases where the array size reaches the limit. Might need some review on how big an impact this would be.

The maximum length of float to decimal is 15, and the maximum length of double to decimal is 24. The original exception handling was because the Appendable#append(char) method threw an IOException, which is no longer necessary.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/19730#discussion_r1640755241


More information about the core-libs-dev mailing list