Looking for Cloud Services or Professional Support? Check restheart.com

GraalVM

Introduction

GraalVM is a new virtual machine from Oracle that supports a polyglot runtime environment and the ability to compile Java applications to native images.

RESTHeart fully supports the GraalVM:

  • you can run RESTHeart using the GraalVM
  • starting from v5.2, you can build RESTHeart (and your custom plugins) to a native image using GraalVM’s native-image tool

Why GraalVM

GraalVM provides advanced optimizing compiler that generates fast lean code which requires fewer compute resources and allows Ahead-of-Time Compilation to build Native binaries that start up instantly and deliver peak performance with no warm up time.

Startup time
Memory Footprint

Images from graalvm.org website.

Benefits of running RESTHeart with the GraalVM

The GraalVM is faster than OpenJDK and it is also a polyglot runtime environment, so that you can seamlessly use multiple languages to implement RESTHeart plugins.

In the v5.2 product line we will progressively leverage the GraalVM to allow you to develop plugins, such as services and interceptors by just defining JavaScript lambda functions.

Benefits of running RESTHeart as a native image

Building a RESTHeart application to native image provides multiple advantages, including faster startup time and smaller memory footprint.

A RESTHeart application is a bundle of RESTHeart core and plugins. The plugins can include the one shipped with RESTHeart (restheart-mongodb.jar and restheart-security.jar) and custom plugins that implement your application logic.

The following table compares RESTHeart (with default plugins) running on a MacBook Pro with OpenJDK, GraalVM CE and GraalVM CE native image.

  OpenJDK GraalVM CE GraalVM CE native
startup time 2441ms 2042ms 249ms
memory 487Mbyte 761Mbyte 279Mbyte
integration test execution time 63,503s 57,292s 52,518s

The numbers clearly show that running RESTHeart as a native image is ideal for microservices and clustering. With instant startup time and smaller memory footprint you can run multiple instances of RESTHeart Docker images and also better support dynamic scaling.

In some use cases, native image might result in slightly worse peak performance. Read this great article for more information. The fact that peak performances might be worse, is well compensated by the ability to run more RESTHeart instances in parallel due to much smaller memory footprint.

Install the GraalVM

We suggest to install GraalVM with sdkman

$ sdk install java 20.3.0.r11-grl

After having installed GraalVM, you can install the native-image tool with gu

$ gu install native-image

Run RESTHeart with GraalVM

Check that GraalVM SDK is active:

$ java -version
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)

Then just run RESTHeart as usual:

$ java -jar restheart.jar etc/restheart.yml -e etc/default.properties

Build RESTHeart with default plugins as native image

RESTHeart’s pom.xml includes the native profile.

Check that GraalVM SDK is active:

$ java -version
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)

You can then simply build it with:

$ git checkout https://github.com/SoftInstigate/restheart.git
$ cd restheart
$ mvn clean package -Pnative

As a result, you’ll find the executable binary file target/restheart-native.

Build RESTHeart with custom plugins as native image

In order to build RESTHeart with custom plugins as native image you use maven to:

At startup time, RESTHeart dynamically loads the plugins jars found in the /plugins directory. Dynamic class loading is simply not possible with GraalVM. This is why you need to package RESTHeart core and all plugins in a uber-jar.

Define the Maven native profile following this example pom.xml.

You can now build the native image with:

$ mvn clean package -Pnative

In order for some java features to work, like reflection, you might need to tweak the native image build properties found in the repo directory core/src/main/resources/META-INF/native-image/org.restheart/restheart.

For further information, good starting points are:

A docker image to build Linux native images

SoftInstigate maintains the Debian based, docker image softinstigate/graalvm-maven with GraalVM and Maven and native-image.

Use it if you are running a different OS and you need to build a native image for Linux to include it in a Docker image.

$ docker pull softinstigate/graalvm-maven

You can build a Linux native image with:

$ docker run -it --rm \
    -v "$PWD":/opt/app  \
    -v "$HOME"/.m2:/root/.m2 \
    softinstigate/graalvm-maven \
    clean package -Pnative