Ok, here's a test...
with just the following change:
diff -r 9ea9fb3c0c88 src/java.base/share/classes/java/math/BigInteger.java
--- a/src/java.base/share/classes/java/math/BigInteger.java Wed Mar
23 18:24:35 2016 +0100
+++ b/src/java.base/share/classes/java/math/BigInteger.java Wed Mar
23 19:55:01 2016 +0100
@@ -41,6 +41,7 @@
import jdk.internal.math.DoubleConsts;
import jdk.internal.math.FloatConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.Stable;
/**
* Immutable arbitrary-precision integers. All operations behave as if
@@ -1213,8 +1214,10 @@
* Initialize static constant array when class is loaded.
*/
private static final int MAX_CONSTANT = 16;
- private static BigInteger posConst[] = new BigInteger[MAX_CONSTANT+1];
- private static BigInteger negConst[] = new BigInteger[MAX_CONSTANT+1];
+ @Stable
+ private static final BigInteger posConst[] = new
BigInteger[MAX_CONSTANT+1];
+ @Stable
+ private static final BigInteger negConst[] = new
BigInteger[MAX_CONSTANT+1];
/**
* The cache of powers of each radix. This allows us to not have to
The results of simple benchmark:
/*
Original:
Benchmark Mode Cnt Score Error Units
BigIntegerBench.ONE avgt 10 2.396 ± 0.232 ns/op
BigIntegerBench.valueOf_1 avgt 10 2.846 ± 0.233 ns/op
BigIntegerBench.valueOf_2 avgt 10 2.808 ± 0.054 ns/op
Patched:
Benchmark Mode Cnt Score Error Units
BigIntegerBench.ONE avgt 10 2.381 ± 0.126 ns/op
BigIntegerBench.valueOf_1 avgt 10 2.347 ± 0.089 ns/op
BigIntegerBench.valueOf_2 avgt 10 2.323 ± 0.022 ns/op
*/
package jdk.test;
import org.openjdk.jmh.annotations.*;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@Fork(1)
@Warmup(iterations = 5)
@Measurement(iterations = 10)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class BigIntegerBench {
@Benchmark
public BigInteger ONE() {
return BigInteger.ONE;
}
@Benchmark
public BigInteger valueOf_1() {
return BigInteger.valueOf(1);
}
@Benchmark
public BigInteger valueOf_2() {
return BigInteger.valueOf(2);
}
}
So, no need to change the API and all uses of valueOf(-MAX_CONSTANT <= i
<= MAX_CONSTANT) for constant 'i' will be faster a bit.
Regards, Peter
On 03/23/2016 07:01 PM, Peter Levart wrote:
Hi Xuelei,
On 03/23/2016 04:26 AM, Xuelei Fan wrote:
Hi,
Please review the update for the supporting of BigInteger.TWO:
http://cr.openjdk.java.net/~xuelei/8152237/webrev/
BigInteger.valueOf(2) is a common BigInteger value used in binary and
cryptography operation calculation. The BigInteger.TWO is not
exported, and hence BigInteger.valueOf(2) is used instead in
applications and JDK components. The export of static BigInteger.TWO
can improve performance and simplify existing code.
Thanks,
Xuelei
I think (haven't tried, just speculate) you could achieve the same
performance by:
- adding final qualifier to static BigInteger.[posConst|negConst] fields
- annotating those fields with @jdk.internal.vm.annotation.Stable
annotation
This way BigInteger.valueOf(-MAX_CONSTANT <= i <= MAX_CONSTANT) when
called with a constant argument should fold into a constant when
compiled by JIT.
The same optimization could be performed for valueOf methods of
java.lang.Byte, Character, Short, Integer & Long.
@Stable annotation was a package-private annotation in
java.lang.invoke, reserved for method handles infrastructure, but has
since been made public and moved to a concealed package of java.base.
There is already a precedent for its use outside in java.lang.invoke:
in java.lang.String. For example:
static final String s = ".....";
s.charAt(0); // is folded into a constant by JIT
Regards, Peter