RFR: 8205592: BigDecimal.doubleValue() is depressingly slow

Andriy Plokhotnyuk duke at openjdk.org
Mon Feb 13 17:58:30 UTC 2023


On Tue, 31 Jan 2023 13:39:46 GMT, Raffaello Giulietti <rgiulietti at openjdk.org> wrote:

>> A reimplementation of `BigDecimal.[double|float]Value()` to enhance performance, avoiding an intermediate string and its subsequent parsing on the slow path.
>
> This PR is waiting for a review

@rgiulietti Thanks for keeping making JDK faster!

I have a couple of review comments:

#### 1) For the line https://github.com/openjdk/jdk/pull/9410/files#diff-94d400b99466045dd76001c37eada6b24d086d8d115b49c439752bbceb233772L3746

It seems that removing this check for 22-bit number introduces an extra rounding error.

Please consider just increasing the constant up to `1L << 32` and using `DOUBLE_10_POW` instead of `FLOAT_10_POW`.

Bellow are REPL expressions that illustrate my thoughts (sorry for using Scala):

$ scala
Welcome to Scala 3.2.0 (17.0.5, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                                                                                                                   
scala> new java.math.BigDecimal("167772170E-1").floatValue
val res0: Float = 1.6777216E7
                                                                                                                                                                                                                   
scala> 167772170E-1f
val res1: Float = 1.6777216E7
                                                                                                                                                                                                                   
scala> 167772170 / 10.0f
val res2: Float = 1.6777218E7

scala> (167772170 / 10.0).toFloat
val res3: Float = 1.6777216E7

#### 2) For the line: https://github.com/openjdk/jdk/pull/9410/files#diff-94d400b99466045dd76001c37eada6b24d086d8d115b49c439752bbceb233772L3791

It seems that removing this check for 52-bit number introduces an extra rounding error:

$ scala
Welcome to Scala 3.2.0 (17.0.6, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> new java.math.BigDecimal("90071992547409930E-1").doubleValue
val res0: Double = 9.007199254740992E15
                                                                                                                                                                                                                   
scala> 90071992547409930E-1
val res1: Double = 9.007199254740992E15
                                                                                                                                                                                                                   
scala> 90071992547409930L / 10.0
val res2: Double = 9.007199254740994E15

#### 3) For the line: https://github.com/openjdk/jdk/pull/9410/files#diff-94d400b99466045dd76001c37eada6b24d086d8d115b49c439752bbceb233772L3800
Here before falling back to the costly fallback with big number operations we can [get a number of digits in intCompact](https://github.com/plokhotnyuk/jsoniter-scala/blob/6f702ce5cae05df91b5aa6e4bd61acdf43bf18f6/jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala#L1930) and use [a trick with two multiplications](https://github.com/plokhotnyuk/jsoniter-scala/blob/6f702ce5cae05df91b5aa6e4bd61acdf43bf18f6/jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonReader.scala#L1459)

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

PR: https://git.openjdk.org/jdk/pull/9410


More information about the core-libs-dev mailing list