GraalVM demos: Native images for faster startup
This is a sample application to demonstrate GraalVM capabilities for creating native images.
- Download or clone the repository and navigate into the
git clone https://github.com/graalvm/graalvm-demos cd graalvm-demos/native-list-dir
There are two Java classes, but we will start by building
ListDir.javafor the purposes of this demo. You can manually execute
javac ListDir.java, there is also a
build.shscript included for your convenience. Note that you can use any JDK for compiling the Java classes, however we refer to
javacfrom GraalVM in the build script to simplify the prerequisites and not to depend on another JDK installed.
- Having downloaded and unzipped GraalVM CE or EE archive, export the GraalVM home directory as the
$GRAALVM_HOME/binto the path, using a command-line shell for Linux:
and for macOS:
Note that your paths are likely to be different depending on the download location.
Make sure the
native-imageutility is available. Starting from GraalVM 19.0, Native Image was extracted from the base distribution. This functionality can be added to the core installation with GraalVM Updater tool by running:
gu install native-image.
- Then execute:
build.sh script creates a native image from the Java class.
Let us look at it in more detail:
native-image utility ahead-of-time compiles the
ListDir class into a
standalone binary in the current working directory. After running the
command, an executable file
listdir should have been produced.
Running the Application
To run the application, you need to either execute the
as a normal Java application using
java, or, since we have a native image
prepared, run that directly.
run.sh file, executes both, and times them with the
time java ListDir $1 time ./listdir $1
To make it more interesting, pass it to a parent directory:
./run.sh .. (
.. - is
the parent of the current directory, the one containing all the demos).
Approximately, the following output should be produced:
+ java ListDir .. Walking path: .. Total: 141 files, total size = 14448801 bytes real 0m0.320s user 0m0.379s sys 0m0.070s + ./listDir .. Walking path: .. Total: 141 files, total size = 14448801 bytes real 0m0.030s user 0m0.005s sys 0m0.011s
The performance gain of the native version is largely due to the faster startup.
You can also experiment with a more sophisticated
To compile that class you need to add
graal-sdk.jar on the classpath:
$GRAALVM_HOME/bin/javac -cp $GRAALVM_HOME/jre/lib/boot/graal-sdk.jar ExtListDir.java
native-image utility about it by passing the
$GRAALVM_HOME/bin/native-image --language:js ExtListDir
The execution is the same as in the previous example:
time java ExtListDir $1 time ./extlistdir $1
Profile-Guided Optimizaitons for High Throughput
GraalVM Enterprise Edition offers extra benefits for building a native image. These are profile-guided optimisations (PGO). As an example we will use a small application demonstrating Java streams.
First, we run the application with
java to see the output:
+ javac Streams.java + $GRAALVM_HOME/bin/native-image Streams + ./streams 1000000 200 ... Iteration 20 finished in 1955 milliseconds with checksum 6e36c560485cdc01
To enable PGO we need to build an instrumented image and run it to collect profiles:
+ $GRAALVM_HOME/bin/native-image --pgo-instrument Streams + ./streams 1000 200
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 we can use these profiles to make an optimized image:
+ $GRAALVM_HOME/bin/native-image --pgo Streams
When we run the PGO image with
+ ./streams 1000000 200 ... Iteration 20 finished in 827 milliseconds with checksum 6e36c560485cdc01
we will see more than 2x improvements in performance.