JDK-6992335 : Asymmetric performance of BigInteger.multiply
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.math
  • Affected Version: 6u22
  • Priority: P4
  • Status: Resolved
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2010-10-15
  • Updated: 2013-02-06
  • Resolved: 2013-02-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Resolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)


A DESCRIPTION OF THE PROBLEM :
The method "multiply" in class java.math.BigInteger is twice as slow as it needs to be when called on a large number with a smaller number as a parameter.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run supplied code
2. Observe different performance characteristics for the two different methods

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Performance characteristics should be the same in both cases.
ACTUAL -
One method is twice as slow as the other.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.math.BigInteger;

public class Factorial
{
    public static BigInteger fact1 (BigInteger n)
    {
        BigInteger n0 = n;
        BigInteger f = BigInteger.ONE;
        while (n0.compareTo (BigInteger.ZERO) > 0)
        {
            f = n0.multiply (f);
            n0 = n0.subtract (BigInteger.ONE);
        }

        return f;
    }

    public static BigInteger fact2 (BigInteger n)
    {
        BigInteger n0 = n;
        BigInteger f = BigInteger.ONE;
        while (n0.compareTo (BigInteger.ZERO) > 0)
        {
            f = f.multiply (n0);
            n0 = n0.subtract (BigInteger.ONE);
        }

        return f;
    }

    public static void main (String[] args)
    {
        BigInteger n = BigInteger.valueOf (5000);
        System.out.println ("Doing factorial for " + n);
        long t0 = System.currentTimeMillis ();
        fact1 (n);
        long t1 = System.currentTimeMillis ();
        fact2 (n);
        long t2 = System.currentTimeMillis ();
        System.out.println ("Method 1 took " + (t1 - t0) + "ms");
        System.out.println ("Method 2 took " + (t2 - t1) + "ms");
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Where performance is critical, add a check on the magnitude of the numbers before multiplying.

Comments
Based on running the supplied test case and other micro-benchmarks, this issue appears to have been resolved by this changeset: changeset: 4512:ffada2ce20e5 user: darcy date: Thu Sep 01 23:00:09 2011 -0700 summary: 7082971: More performance tuning of BigDecimal and other java.math classes The performance discrepancy is no longer reproducible: the same performance is observed for both paths.
06-02-2013