RFR: 8327791: Optimization for new BigDecimal(String) [v3]

Shaojin Wen duke at openjdk.org
Mon Mar 11 18:23:55 UTC 2024


On Mon, 11 Mar 2024 18:03:06 GMT, Shaojin Wen <duke at openjdk.org> wrote:

>> The current BigDecimal(String) constructor calls String#toCharArray, which has a memory allocation.
>> 
>> 
>> public BigDecimal(String val) {
>>     this(val.toCharArray(), 0, val.length()); // allocate char[]
>> }
>> 
>> 
>> When the length is greater than 18, create a char[]
>> 
>> 
>> boolean isCompact = (len <= MAX_COMPACT_DIGITS); // 18
>> if (!isCompact) {
>>     // ...
>> } else {
>>     char[] coeff = new char[len]; // allocate char[]
>>     // ...
>> }
>> 
>> 
>> This PR eliminates the two memory allocations mentioned above, resulting in an approximate 60% increase in performance..
>
> Shaojin Wen has updated the pull request incrementally with two additional commits since the last revision:
> 
>  - less duplicate code
>  - add more benchmark

I also prefer to reduce duplicate code. There are not many scenarios where BigDecima(char[]) is used. The most commonly used scenario is BigDecimal(String).

If performance is very important, the user can implement the parser by himself, similar to MysqlBinaryValueDecoder#decodeDecimal. He can remove the StringUtils.toAsciiCharArray conversion and implement the parser based on ascii.

I added some benchmarks, and the numbers show that the performance drops by 21.67% in the SmallCharArray scene, and by 6.52% and 5.69% in the LargeCharArray and HugeCharArray scenes.


-Benchmark                                      Mode  Cnt    Score   Error  Units #master
-BigDecimals.testConstructorWithSmallCharArray  avgt   15   16.488 ? 0.054  ns/op
-BigDecimals.testConstructorWithLargeCharArray  avgt   15   90.583 ? 1.523  ns/op
-BigDecimals.testConstructorWithHugeCharArray   avgt   15   90.683 ? 1.623  ns/op
-BigDecimals.testConstructorWithCharArray       avgt   15   47.418 ? 0.473  ns/op
-BigDecimals.testConstructorWithSmallString     avgt   15   19.725 ? 0.049  ns/op
-BigDecimals.testConstructorWithLargeString     avgt   15  113.567 ? 1.470  ns/op
-BigDecimals.testConstructorWithHugeString      avgt   15  119.712 ? 6.230  ns/op
-BigDecimals.testConstructorWithString          avgt   15   67.046 ? 0.979  ns/op


+Benchmark                                      Mode  Cnt    Score   Error  Units (01 #61b5531b)
+BigDecimals.testConstructorWithSmallCharArray  avgt   15   14.322 ? 0.063  ns/op +15.12%
+BigDecimals.testConstructorWithLargeCharArray  avgt   15   74.090 ? 0.299  ns/op +22.26%
+BigDecimals.testConstructorWithHugeCharArray   avgt   15   74.372 ? 0.461  ns/op +21.93%
+BigDecimals.testConstructorWithCharArray       avgt   15   41.606 ? 0.284  ns/op +13.96%
+BigDecimals.testConstructorWithSmallString     avgt   15   15.019 ? 0.100  ns/op +31.33%
+BigDecimals.testConstructorWithLargeString     avgt   15   70.226 ? 0.240  ns/op +61.71%
+BigDecimals.testConstructorWithHugeString      avgt   15   70.153 ? 0.455  ns/op +70.64%
+BigDecimals.testConstructorWithString          avgt   15   40.064 ? 0.298  ns/op +67.36%

+Benchmark                                      Mode  Cnt    Score   Error  Units (02 #bdf9f4b5)
+BigDecimals.testConstructorWithSmallCharArray  avgt   15   21.052 ? 0.109  ns/op -21.67%
+BigDecimals.testConstructorWithLargeCharArray  avgt   15   96.911 ? 2.921  ns/op -6.52%
+BigDecimals.testConstructorWithHugeCharArray   avgt   15   96.158 ? 3.501  ns/op -5.69%
+BigDecimals.testConstructorWithCharArray       avgt   15   54.673 ? 2.563  ns/op -13.26%
+BigDecimals.testConstructorWithSmallString     avgt   15   15.061 ? 0.082  ns/op +30.96%
+BigDecimals.testConstructorWithLargeString     avgt   15   70.670 ? 0.607  ns/op +60.70%
+BigDecimals.testConstructorWithHugeString      avgt   15   70.706 ? 0.531  ns/op +69.30%
+BigDecimals.testConstructorWithString          avgt   15   39.869 ? 0.149  ns/op +68.16%

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

PR Comment: https://git.openjdk.org/jdk/pull/18177#issuecomment-1989144767


More information about the core-libs-dev mailing list