Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Java JIT cheat when running JDK code?

I was benchmarking some code, and I could not get it to run as fast as with java.math.BigInteger, even when using the exact same algorithm. So I copied java.math.BigInteger source into my own package and tried this:

//import java.math.BigInteger;  public class MultiplyTest {     public static void main(String[] args) {         Random r = new Random(1);         long tm = 0, count = 0,result=0;         for (int i = 0; i < 400000; i++) {             int s1 = 400, s2 = 400;             BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r);             long tm1 = System.nanoTime();             BigInteger c = a.multiply(b);             if (i > 100000) {                 tm += System.nanoTime() - tm1;                 count++;             }             result+=c.bitLength();         }         System.out.println((tm / count) + "nsec/mul");         System.out.println(result);      } } 

When I run this (jdk 1.8.0_144-b01 on MacOS) it outputs:

12089nsec/mul 2559044166 

When I run it with the import line uncommented:

4098nsec/mul 2559044166 

It's almost three times as fast when using the JDK version of BigInteger versus my version, even if it's using the exact same code.

I've examined the bytecode with javap, and compared compiler output when running with options:

-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions  -XX:+PrintInlining -XX:CICompilerCount=1 

and both versions seem to generate the same code. So is hotspot using some precomputed optimisations that I can't use in my code? I always understood that they don't. What explains this difference?

like image 267
Koen Hendrikx Avatar asked Aug 28 '17 05:08

Koen Hendrikx


People also ask

How does Java JIT work?

The JIT compiler is enabled by default, and is activated when a Java method is called. The JIT compiler compiles the bytecodes of that method into native machine code, compiling it "just in time" to run. When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting it.

Where is JIT compiled code stored?

Answer 2: The JVM keeps the JITCed code for each method in C heap, linked to via tables in the internal representation of the class object.

What is JIT compilation Java?

The Just-In-Time (JIT) compiler is a component of the runtime environment that improves the performance of Java™ applications by compiling bytecodes to native machine code at run time.


1 Answers

Yes, HotSpot JVM is kind of "cheating", because it has a special version of some BigInteger methods that you won't find in Java code. These methods are called JVM intrinsics.

In particular, BigInteger.multiplyToLen is an instrinsic method in HotSpot. There is a special hand-coded assembly implementation in JVM source base, but only for x86-64 architecture.

You may disable this instrinsic with -XX:-UseMultiplyToLenIntrinsic option to force JVM to use pure Java implementation. In this case the performance will be similar to the performance of your copied code.

P.S. Here is a list of other HotSpot intrinsic methods.

like image 174
apangin Avatar answered Oct 02 '22 17:10

apangin