Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8152910

Get performance improvement with Stable annotation

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 12
    • None
    • core-libs
    • b16

      Peter Levart posted in OpenJDK:
      ------------------------------------------
      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


      Peter Levart evaluation in OpenJDK:
      ----------------------------------------------
       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.

            bpb Brian Burkhalter
            xuelei Xuelei Fan
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: