GraalVM demos: Native images for faster startup

This is a sample application to demonstrate GraalVM capabilities for creatingnative images.

Preparation

• Download or clone the repository and navigate into the native-list-dir directory:
git clone https://github.com/graalvm/graalvm-demoscd graalvm-demos/native-list-dir

There are two Java classes, but we will start by building ListDir.java for thepurposes of this demo. You can manually execute javac ListDir.java, there isalso a build.sh script included for your convenience. Note that you can useany JDK for compiling the Java classes, however we refer to javac from GraalVMin the build script to simplify the prerequisites and not to depend on anotherJDK installed.

• Having downloaded and unzipped GraalVM CE or EE archive, export the GraalVM home directory as the $GRAALVM_HOME and add $GRAALVM_HOME/binto the path, using a command-line shell for Linux:
export GRAALVM_HOME=/home/${current_user}/path/to/graalvm and for macOS: export GRAALVM_HOME=/Users/${current_user}/path/to/graalvm/Contents/Home

Note that your paths are likely to be different depending on the download location.

• Make sure the native-image utility 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

The build.sh script creates a native image from the Java class.

Let us look at it in more detail:

$GRAALVM_HOME/bin/native-image ListDir The native-image utility ahead-of-time compiles the ListDir class into astandalone binary in the current working directory. After running thecommand, an executable file listdir should have been produced. Running the Application To run the application, you need to either execute the ListDir class,as a normal Java application using java, or, since we have a native imageprepared, run that directly. The run.sh file, executes both, and times them with the time utility. time java ListDir$1time ./listdir $1 To make it more interesting, pass it to a parent directory: ./run.sh .. (.. - isthe 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 bytesreal 0m0.320suser 0m0.379ssys 0m0.070s+./listDir ..Walking path:..Total:141 files, total size =14448801 bytesreal 0m0.030suser 0m0.005ssys 0m0.011s The performance gain of the native version is largely due to the faster startup. Polyglot Capabilities You can also experiment with a more sophisticated ExtListDir example,which uses Java/JavaScript polyglot capabilities. 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 Building the native image command is similar to the one above, but, since we want to use JavaScript, we need to inform the native-image utility about it by passing the —language:js option.Note that it takes a bit more time because it needs to include the JavaScript support. $GRAALVM_HOME/bin/native-image --language:js ExtListDir

The execution is the same as in the previous example:

time java ExtListDir $1time ./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 1000000200...Iteration20 finished in1955 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 1000200

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 1000000200...Iteration20 finished in827 milliseconds with checksum 6e36c560485cdc01

we will see more than 2x improvements in performance.