11 апр. 2024

Speed up the Java app startup time, part -2 : using CRaC with Spring boot 3.2

It's the second part of the series "Speed up the Java app startup time.". In this part, I am going to explore the CRaC JDK project to show how to use and decrease the application startup time.

JDK project CRaC [1] or Coordinated Restore at Checkpoint is a research project that allows you to start a Java application in a very short time. In other words, with these features, you can take a snapshot of your application at any moment and then restore the application from the snapshot. Even more, you can start any number of instance of the application from the snapshot. Snapshot stores locally on machines or on the Docker container.

This project is under development and not included in the open JDK version yet. Although CRaC is also introduced with Spring Boot 3.2 as an initial support, the project contains a few limitations:

  1. The feature is not included in OpenJDK version; you have to use JDK with CraC support, like Zulu [2]

  2. The feature is available on Linux only. Azul Zulu Build of OpenJDK with CRaC support for MacOS and Windows only provides a simulated checkpoint/restore mechanism to be used for development and testing

  3. SDK Manager on MacOS doesn't provide any Open JDK version with CRaC support.

  4. The open JDK version with CRaC should be installed/extracted with sudo.

  5. org.crac Maven/Gradle dependency

  6. A folder location for storing the snapshot

So, cut a long history short. Let's pull a spring boot project from the Git Hub and try the CRaC feature.

Step 1. Download or pull the sample project from the Git Hub repository [3]. The project contains a REST service which will return 3 Customers ID and names using the given URL, "/customers"

The interesting part is the dependency:

<dependency>
  <groupId>org.crac</groupId>
  <artifactId>crac</artifactId>
  <version>1.4.0</version>
</dependency> 

This library provides the CRaC feature right out of the box for any Java application. Add this library to build an application that uses the CRaC API, to be able to run it on Java runtimes with CRaC, or without any implementation.

Step 2. Download and install the Azul Zulu Build of OpenJDK with CRaC support. Note that JDK should be installed with sudo. Don't forget to add the JDK in your class path.

Step 3. Build the project as shown below:

mvn clean package

Step 4. Run the application with the following command:

java -XX:CRaCCheckpointTo=./checkpoint_store -jar ./target/spring-boot-crac-0.0.1-SNAPSHOT.jar

Note the -XX:CRaCCheckpointTo command line option. It will provide you with the ability to take any snapshot manually, for example, 10 minutes later when the application starts.

Step 5. On another terminal, run the following command:

jcmd ./target/spring-boot-crac-0.0.1-SNAPSHOT.jar JDK.checkpoint

The above command will start the process of taking snapshots. After completing the process, all two processes will be killed.

2024-04-11T14:52:50.892Z  INFO 1473 --- [Attach Listener] jdk.crac                                 : Starting checkpoint
Killed

Check the folder checkpoint_store to explore the files.

You should find a lot of images to store the state of the application. Now, it's time to restore the application from the snapshot.

Step 6. Run the following command from another terminal.

java -XX:CRaCRestoreFrom=./checkpoint_store

The command will start the application from the snapshot.

shamim@java-features:java -XX:CRaCRestoreFrom=./checkpoint_store
2024-04-11T14:53:32.626Z  INFO 1473 --- [Attach Listener] o.s.c.support.DefaultLifecycleProcessor  : Restarting Spring-managed lifecycle beans after JVM restore
2024-04-11T14:53:32.636Z  INFO 1473 --- [Attach Listener] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path ''
2024-04-11T14:53:32.637Z  INFO 1473 --- [Attach Listener] o.s.c.support.DefaultLifecycleProcessor  : Spring-managed lifecycle restart completed (restored JVM running for 30 ms)

Note the restored time: 30 ms ;-) Impressive?


What's next? Try to use the feature on Docker containers and K8.


References:

[1]. https://openjdk.org/projects/crac/

[2]. https://www.azul.com/downloads/?os=ubuntu&architecture=x86-64-bit&package=jdk-crac#zulu

[3]. https://github.com/srecon/Developing_Reactive_app/tree/master/21issues/spring-boot-crac