RFR: 8310813: Simplify and modernize equals, hashCode, and compareTo for BigInteger [v3]

Pavel Rappo prappo at openjdk.org
Tue Jul 25 13:51:12 UTC 2023


On Thu, 20 Jul 2023 15:32:09 GMT, Pavel Rappo <prappo at openjdk.org> wrote:

>> Please review this PR to use modern APIs and language features to simplify equals, hashCode, and compareTo for BigInteger. If you have any performance concerns, please raise them.
>> 
>> This PR is cherry-picked from a bigger, not-yet-published PR, to test the waters. That latter PR will be published soon.
>
> Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision:
> 
>  - Restore hash code values
>    
>    BigInteger is old and ubiquitous enough so that there might be
>    inadvertent dependencies on its hash code.
>    
>    This commit also includes a test, to make sure hash code is
>    unchanged.
>  - Merge branch 'master' into 8310813
>  - Add a benchmark
>  - Merge branch 'master' into 8310813
>  - Use fewer range checks to improve performance
>  - Improve
>  - Initial commit

Made benchmarks more sensible. Bit length, which is a sole benchmark parameter, is now based on stats I gathered from running tests in the security area, which seems to be the biggest client of BigInteger in JDK. `equals` and `compareTo` now benchmark the worst-case scenario: each method compares two numbers whose binary representations differ minimally.

<details>
<summary>Here's how to replicate my stats, if required...</summary>

1. Add logging to `equals`, `hashCode`, and `compareTo`:

   ```
   diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java
   index 1803b77df54..214a9ce4e4f 100644
   --- a/src/java.base/share/classes/java/math/BigInteger.java
   +++ b/src/java.base/share/classes/java/math/BigInteger.java
   @@ -3924,6 +3924,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
         */
        @Override
        public int compareTo(BigInteger val) {
   +        System.out.println("#cmp#" + Math.min(this.bitLength(), val.bitLength()));
            if (signum == val.signum) {
                return switch (signum) {
                    case 1  -> compareMagnitude(val);
   @@ -4016,6 +4017,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
            if (!(x instanceof BigInteger xInt))
                return false;
    
   +        System.out.println("#eq#" + Math.min(this.bitLength(), xInt.bitLength()));
   +
            if (xInt.signum != signum)
                return false;
    
   @@ -4055,6 +4058,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
         */
        @Override
        public int hashCode() {
   +        System.out.println("#hc#" + bitLength());
            return ArraysSupport.vectorizedHashCode(mag, 0, mag.length, 0,
                    ArraysSupport.T_INT) * signum;
        }
   ```

2. Run tests:

   ```
   jtreg -J-Djavatest.maxOutputSize=999999999 -retain:all -verbose:summary -testjdk:build/macosx-aarch64/images/jdk/ test/jdk/:jdk_security
   ```

3. Ensure that the output is complete, that is, there are no "Output overflow:" in the jtr files. If there are, you might not be seeing the full data; increase the `maxOutputValue`, repeat step 2.

**Note: besides taking considerable time to run, this test configuration results in the JTwork directory whose size is 4G.**
</details>

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

PR Comment: https://git.openjdk.org/jdk/pull/14630#issuecomment-1649878980


More information about the core-libs-dev mailing list