This demo shows how GraalVM efficiently removes abstractions from high-level programs.
The Streams.java
file contains a simple query implemented with the Java Streams API:
Arrays.stream(persons)
.filter(p -> p.getEmployment() == Employment.EMPLOYED)
.filter(p -> p.getSalary() > 100_000)
.mapToInt(Person::getAge)
.filter(age -> age > 40)
.average()
.getAsDouble();
-
Run this stream with any
java
you have on your system:javac Streams.java
java Streams 100000 200
Iteration 20 finished in 114 milliseconds with checksum e6e0b70aee921601 TOTAL time: 2330
-
Download and install the latest GraalVM JDK using SDKMAN!.
sdk install java 21.0.1-graal
-
Now compile and run the same application on GraalVM:
$JAVA_HOME/bin/javac Streams.java
$JAVA_HOME/bin/java Streams 100000 200
Iteration 20 finished in 21 milliseconds with checksum e6e0b70aee921601 TOTAL time: 623
We can see over 4x speedup on this simple program.
This demo shows how to use profile-guided optimizations (PGO) with the native-image
builder.
Note: Profile-guided optimizations is a GraalVM Enterprise feature.
You will use the same Streams.java
program that contains a simple query implemented with the Java Streams API:
Arrays.stream(persons)
.filter(p -> p.getEmployment() == Employment.EMPLOYED)
.filter(p -> p.getSalary() > 100_000)
.mapToInt(Person::getAge)
.filter(age -> age > 40)
.average()
.getAsDouble();
-
First, build the native image without profile-guided optimizations:
$JAVA_HOME/bin/javac Streams.java
$JAVA_HOME/bin/native-image Streams
./streams 100000 200
Iteration 20 finished in 127 milliseconds with checksum e6e0b70aee921601 TOTAL time: 2589
This version of the program runs about 2x slower than the one on the regular JDK.
-
To enable PGO you need to build an instrumented image:
$JAVA_HOME/bin/native-image --pgo-instrument Streams
-
Run this instrumented image to collect profiles:
./streams 10000 200
Iteration 20 finished in 62 milliseconds with checksum e1d39d010d08cf01 TOTAL time: 1279
Profiles collected from this run are now stored in the default.iprof file.
Note that we run the profiling with a much smaller data size.
-
Now you can use the collected profiles to build an optimized native image:
$JAVA_HOME/bin/native-image --pgo Streams
-
Then run it:
./streams 100000 200
Iteration 20 finished in 24 milliseconds with checksum e6e0b70aee921601 TOTAL time: 516
You should get the performance comparable to the Java version of the program.