Skip to main content
Loading...

Spring Boot 3

Inspiring technology by Hunters

Our Hunters continue to bring us more tech news. This time, they tell us about Spring Boot 3 and one of its main new features: native project compilation.

Native compilation produces executable code for a specific architecture, without having to rely on Java Virtual Machine. This leads to faster running speed and lower resource usage.

When you compile a project natively, compile-time preprocessing resolves configurations that are normally established at project initiation during runtime. Optimisations such as the removal of unused code are also performed, resulting in much faster start-up, higher performance and lower resource usage.

This directly generates a Docker image based on GraalVM, a system designed to run Java programmes with high performance.

Native compilation is especially useful in serverless environments with functions-as-a-service, where there are limited resources available and fast initialisation is required.
 

Project testing

We compiled the same project natively and in the standard way, and obtained the following data:

Compilación de datos de proyectos en forma nativa y estándar.

 

Native and standar project data compilation.

Limitations and compatibilities

Native Spring compilation initialises the project configurations, establishing the classpath and the beans to be injected with a static method, making it impossible to modify them at runtime.

Additionally, using GraalVM limits the use of tools such as reflection, which needs to be explicitly indicated in order to be processed at compile time.

Because of this, it is important to be aware of the limitations of native compilations before integrating them into a project.

Project integration

To compile a project natively, you just have to add a plugin within the project:

Añadir un plugin dentro del proyecto.

Once the plugin has been added, the project can be compiled with the following command:

 

compilar el proyecto con el siguiente comando.

When the compilation is complete, a Docker image will have been created with a tag in the format “artifactId:version”.

Initialisations

The same web service has been compiled and executed using native and standard compilation. The following data was obtained from initialisation:

CPU usage
Memory usage

Initialisation times:

  • Native version: 1 second
  • Standard version: 14 seconds

Because the native version has been configured at compile time, it required no CPU usage for initialisation and its RAM usage was constant from the start. In comparison, the standard version required initial CPU usage and time for initialisation.

Batch testing

Tests are carried out on the Command Line Runner interface. These tests consist of one query and one database insert per iteration. We note that these operations were performed using Hibernate.

This test was run with 5,000 iterations and 200,000 iterations, obtaining the following results:

CPU usage command runner (5k)
Memory usage command runner (5k)

 

 

CPU usage command runner (200k)
Memory usage command runner (200k)

Execution times:

  • Native with 5000 iterations:             11s (0.29s initialisation, 8s execution)
  • Standard with 5000 iterations:         23s (9s initialisation, 12s execution)
  • Native with 200000 iterations:         375s (0.26s initialisation, 372s execution)
  • Standard with 200000 iterations:     160s (9s initialisation, 147s execution)

We see that native compilation excels in short jobs, where the initialisation time is more significant, with faster execution time and less resource usage.

On the other hand, native compilation takes considerably longer in bigger jobs. So, although it consumes fewer resources it does so for longer and therefore does not offer an advantage.

Web service stress testing

Stress tests are carried out on a simple web application, with 50 threads, 3 iterations per thread, 50 GET requests and 50 POST requests, creating an entity for each one, and with a wait time of 300 ms between iterations.

CPU usage at stress test (50 threads)
Memory usage at stress test (50 threads)

 

 

Elapsed time at stress test (50 threads)
Latency at stress test (50 threads)

As can be seen, the native version used considerably less RAM overall and less CPU at start-up.

In terms of response time, it is similar to the execution of a batch job: the native version offers considerably better performance at the start of execution, but this performance drops off over time while performance in the standard version improves.

What are the pros and cons of native compilation?

Pros

  • Lower RAM and CPU usage.
  • Smaller image size.
  • Instant initialisation.
  • Unused code is removed during compilation.
  • Shorter execution time in smaller jobs.

Contras

  • High compilation time.
  • Static classpath.
  • Bean resolution at compile time.
  • Inherent GraalVM incompatibilities with certain libraries and tools.

What can we conclude?

According to the tests performed, native Spring compilation is particularly well suited for short runtime executions, consuming considerably fewer resources and with virtually no initialisation time.

These advantages diminish the longer the runtime, as performance deteriorates over time, compared to the standard version, which improves its performance over runtime.

Want to know more about Hunters?

A Hunter rises to the challenge of trying out new solutions, delivering results that make a difference. Join the Hunters programme and become part of a diverse group that generates and transfers knowledge.

Anticipate the digital solutions that will help us grow. Find out more about Hunters on our website.

LinkedIn Joan Galiana

Joan Galiana

Software Technician at Altia