◀Back
Use GraalVM Dashboard to Optimize the Size of a Native Executable
The GraalVM Dashboard is a web-based tool that visualizes the composition of a native executable. It displays the breakdown of packages, classes, and methods included in a native executable, and provides a visual summary of objects that contributed most to its heap size. The GraalVM Dashboard uses report files created by the native image builder. (For more information, see GraalVM Getting Started.)
This guide demonstrates how to use the dashboard to optimize the size of a native executable. It introduces two implementations of a “fortune” sample application that simulate the traditional fortune
Unix program (for more information, see fortune).
Note: This guide assumes you have installed Maven.
Fortune
Package the contents of the first implementation (fortune) as a native executable and review its composition.
-
Make sure you have installed a GraalVM JDK. The easiest way to get started is with SDKMAN!. For other installation options, visit the Downloads section.
- Download or clone the repository and navigate into the fortune-demo/fortune directory:
git clone https://github.com/graalvm/graalvm-demos
cd fortune-demo/fortune
- Build the project:
mvn clean package
- When the build succeeds, run the application on the JVM with the Tracing agent. Since you have installed GraalVM, it will run on GraalVM JDK.
mvn -Pnative -Dagent exec:exec@java-agent
The application will return a random saying. The agent generates the configuration files in the
target/native/agent-output
subdirectory. - Build a native executable of this application with GraalVM Native Image and Maven:
mvn -Pnative -Dagent package
When the command completes, a native executable,
fortune
, is generated in the/target
directory of the project and ready for use. - Run the application by launching a native executable directly:
./target/fortune
The application should slowly print a random phrase.
The application’s pom.xml file employs the Native Image Maven plugin to build a native executable, configured to produce diagnostic data using these two options:
-H:DashboardDump=fortune -H:+DashboardAll
These options result in a file named fortune.bgv. (For more information about different options, see Dumping the Data for GraalVM Dashboard.)
Compare the sizes of the JAR file and the native executable (for example, using
du
):du -sh target/* 0B target/archive-tmp 136K target/classes 17M target/fortune 2.0M target/fortune-1.0-jar-with-dependencies.jar 32K target/fortune-1.0.jar 44M target/fortune.bgv 4.0K target/fortune.build_artifacts.txt 0B target/generated-sources 4.0K target/maven-archiver 8.0K target/maven-status 0B target/test-classes
The size of the JAR file is 2MB, compared to the 17MB size of the native executable. The increase in size is because the native executable contains all necessary runtime code as well as pre-initialized data in its heap.
-
Open the GraalVM Dashboard and load the fortune.bgv file. (Click +, click Select File, select the fortune.bgv file from the target directory, and then click OK.)
The GraalVM dashboard provides two visualizations of a native executable: code size breakdown and heap size breakdown. (For more information, see Code Size Breakdown and Heap Size Breakdown, respectively.)
The screenshot above visualizes the code breakdown of the
fortune
native executable, a great part of which consists of the Jackson JSON parser library implemented in the packagecom.fasterxml
. One approach to reduce the size of a native executable is to minimize the amount of space taken by code. The code size breakdown gives you an insight into the amount of space taken up by the packages that are included in your native executable.Furthermore, the screenshot below shows that the heap of the native executable contains 4MB of Bytes and almost 800KB of Strings. Another approach to reduce the size of a native executable is to minimize the size of its heap.
In the next section, we’ll consider an alternative implementation for the
fortune
application that reduces the amount of code and reduces the size of the heap.
Static Fortune
The first implementation of the fortune application uses the Jackson JSON parser (package com.fasterxml
) at runtime to parse the contents of a resource file that the native image builder has included in the native executable. An alternative implementation (named “staticfortune”) parses the contents of the resource file at build time. This means that the resource file is no longer included in the executable, and the code required to parse the file is omitted from the native executable because it is only required at build time.
- Change to the project directory and build the project:
cd ../staticfortune
mvn clean package
- Run the application on the JVM (GraalVM JDK) with the Tracing agent:
mvn -Pnative -Dagent exec:exec@java-agent
The application will print a random saying. The agent generates the configuration files in the
target/native/agent-output
subdirectory. - Build a static native executable:
mvn -Pnative -Dagent package
When the command completes, a native executable,
staticfortune
, is generated in the/target
directory of the project and ready for use. - Run the demo by launching a native executable directly or with the Maven profile:
./target/staticfortune
The application should behave in exactly the same way as the first implementation.
The application’s pom.xml file again uses the Native Image Maven plugin to build a native executable. However, for this implementation it adds an extra option to initialize class
demo.StaticFortune
at build time:-H:DashboardDump=staticfortune -H:+DashboardAll --initialize-at-build-time=demo.StaticFortune
Compare the sizes of the JAR file and the native executable:
du -sh target/* 0B target/archive-tmp 76K target/classes 0B target/generated-sources 4.0K target/maven-archiver 4.0K target/maven-status 4.3M target/staticfortune 2.0M target/staticfortune-1.0-jar-with-dependencies.jar 32K target/staticfortune-1.0.jar 9.0M target/staticfortune.bgv 4.0K target/staticfortune.build_artifacts.txt 0B target/test-classes
The size of the native executable has reduced in size from 17MB to 4.3MB.
The reduction in size is due to the use of the
--initialize-at-build-time=
argument used with the Native Image Maven plugin. -
The build created a file named staticfortune.bgv. Load it into the GraalVM Dashboard to view the composition of the
staticfortune
native executable.The screenshot above demonstrates that the code in the
com.fasterxml
package is no longer present. There are also reductions in the amount of code included from thejava.util
,java.math
, andjava.text
packages.The screenshot below illustrates that there has also been a significant reduction in the amount of heap given to Strings (767KB versus 184KB), and a reduction in Bytes from 4MB to 862KB.