Experiments with Graal
This chapter details the list of experiments done to use Graal compiler instead of C2 compiler in JVM to compile Java bytecode.
- Compiling Graal
Using Graal compiler
(15Nov'16)
Execution of a program WITHOUT using Graal compiler
To experiment with Graal compiler we will use a simple Java code first.
public class GraalTest {
private int count;
private void callFun(int i){
int a = 3;
count = count + i % 7;
}
public void runBench(){
for(int i=0; i< 255; i++){
callFun(10);
}
}
public static void main(String[] args) {
GraalTest obj = new GraalTest();
for(int i=0; i< Integer.parseInt(args[0]); i++){
obj.runBench();
}
System.out.println("HEELO");
}
}
- An execution of the Java code without using Graal compiler. By adding
-XX:+PrintCompilation
we are printing the compilation information. It prints all the methods getting compiled including the java standard library methods e.g.java.lang.Integer::parseInt
etc. Therefore we are just printing compiled methods fromGraalTest
class.
java -XX:+PrintCompilation GraalTest 10000000 |grep GraalTest
It prints the following compilation information.
95 14 3 GraalTest::callFun (16 bytes)
95 15 4 GraalTest::callFun (16 bytes)
96 14 3 GraalTest::callFun (16 bytes) made not entrant
97 21 3 GraalTest::runBench (22 bytes)
98 24 % 4 GraalTest::runBench @ 2 (22 bytes)
101 30 4 GraalTest::runBench (22 bytes)
103 21 3 GraalTest::runBench (22 bytes) made not entrant
116 33 % 3 GraalTest::main @ 10 (39 bytes)
117 34 3 GraalTest::main (39 bytes)
119 35 % 4 GraalTest::main @ 10 (39 bytes)
132 33 % 3 GraalTest::main @ -2 (39 bytes) made not entrant
644 35 % 4 GraalTest::main @ -2 (39 bytes) made not entrant
Here 3rd column prints a compilation level with 4 as the highest while %
symbol represents On Stack Replace (OSR). More information about PrintCompilation flag output could be found here.
- In above example we are not sure which compiler is getting used for different levels of compilation. To see the compiler information we can use
-XX:CompileCommand=print,*GraalTest.*
command which will print the assembly code of methods getting compiled as well as the compiler name used for compiling a method. We will use grep to print the line containing compiler name.
$ java '-XX:CompileCommand=print,*GraalTest.*' GraalTest 1000000 |grep 'Compiled method'
Java HotSpot(TM) 64-Bit Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c1) 102 14 3 GraalTest::callFun (16 bytes)
Compiled method (c2) 105 17 4 GraalTest::callFun (16 bytes)
Compiled method (c1) 106 21 3 GraalTest::runBench (22 bytes)
Compiled method (c2) 114 24 % 4 GraalTest::runBench @ 2 (22 bytes)
Compiled method (c2) 119 30 4 GraalTest::runBench (22 bytes)
Compiled method (c1) 132 32 % 3 GraalTest::main @ 10 (39 bytes)
Compiled method (c1) 143 33 3 GraalTest::main (39 bytes)
Compiled method (c2) 161 34 % 4 GraalTest::main @ 10 (39 bytes)
In above output the name of compiler (C1 or C2) can be seen.
Execution of a program using Graal compiler
To use graal compiler we need to,
- use
graal.jar
file built from graal-core project (first step). - use flag
-XX:+UseJVMCICompiler
to use JVMCI enabled compiler
$ java -Djvmci.class.path.append=/home/sgaikwad/sandbox/graal/graal.jar \
-XX:+UseJVMCICompiler \
'-XX:CompileCommand=print,*GraalTest.*' \
GraalTest 1000000 |grep 'Compiled '
Java HotSpot(TM) 64-Bit Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c1) 72 13 3 GraalTest::callFun (16 bytes)
Compiled method (c1) 76 20 3 GraalTest::runBench (22 bytes)
Compiled method (c1) 208 217 % 3 GraalTest::main @ 10 (39 bytes)
Compiled method (c1) 222 219 3 GraalTest::main (39 bytes)
Compiled method (JVMCI) 898 16 4 GraalTest::callFun (16 bytes)
Compiled method (JVMCI) 922 24 % 4 GraalTest::runBench @ 2 (22 bytes)
Compiled method (JVMCI) 1369 1386 4 GraalTest::runBench (22 bytes)
Compiled method (JVMCI) 1467 904 % 4 GraalTest::main @ 10 (39 bytes)
- As mentioned in JEP 243 for adding JVMCI, one can provide name of the JVMCI enabled compiler using a flag e.g. for graal compiler
-Djvmci.Compiler=graal
. However, it is important to note that incorrect name of the compiler will throw an exception when it triggers Tier 4 compilation.
$ java -Djvmci.class.path.append=/home/sgaikwad/sandbox/graal/graal.jar \
-XX:+UseJVMCICompiler \
-Djvmci.Compiler=grall \
'-XX:CompileCommand=print,*GraalTest.*' \
GraalTest 1000000
Java HotSpot(TM) 64-Bit Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
.
---skipped output----
.
Compiled method (c1) 110 14 3 GraalTest::callFun (16 bytes)
Compiled method (c1) 115 21 3 GraalTest::runBench (22 bytes)
---skipped output----
Uncaught exception at /scratch/graaluser/buildslave/buildlog/ci_executor/main/graal-jvmci-8/src/share/vm/jvmci/jvmciCompiler.cpp:127
jdk.vm.ci.common.JVMCIError: JVMCI compiler 'grall' not found
at jdk.vm.ci.hotspot.HotSpotJVMCICompilerConfig.getCompilerFactory(HotSpotJVMCICompilerConfig.java:82)
at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.<init>(HotSpotJVMCIRuntime.java:281)
at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.<init>(HotSpotJVMCIRuntime.java:65)
at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime$DelayedInit.<clinit>(HotSpotJVMCIRuntime.java:73)
at jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime(HotSpotJVMCIRuntime.java:83)
at jdk.vm.ci.runtime.JVMCI.initializeRuntime(Native Method)
at jdk.vm.ci.runtime.JVMCI.<clinit>(JVMCI.java:58)
$
Using only Graal compiler for bytecode compilation
- Graal compiler is used when Tier 4 compilation is requested by the JVM (Graal compiler is available along with necessary flags to use it).
- We can force JVM to use only Graal compiler by disabling the Tiered compilation mode of the JVM. Ofcouse, it impacts the overall execution time, especially the startup time.
- Tiered compilation is disabled using flag
-XX:-TieredCompilation
.
$ java -Djvmci.class.path.append=/home/sgaikwad/sandbox/graal/graal.jar \
-XX:+UseJVMCICompiler \
'-XX:CompileCommand=print,*GraalTest.*' \
-XX:-TieredCompilation \
GraalTest 1000000|grep 'Compiled '
Java HotSpot(TM) 64-Bit Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (JVMCI) 2389 2 GraalTest::runBench (22 bytes)
Compiled method (JVMCI) 2390 1 GraalTest::callFun (16 bytes)
$
Resources
[1] Document about 'Printcompilation' flag: https://gist.github.com/rednaxelafx/1165804