Spring Boot vs Eclipse Microprofile
In this article we're going to compare some essential metrics of the web applications using two different Java stacks: Spring Boot and Eclipse Microprofile. And since there are several implementations of the Eclipse Microprofile specifications, we'll be using one of the most famous: Quarkus.
Talking about implementations is important as far as Eclipse Microprofile is concerned because, as opposed to Spring Boot, which is a specification-less Java library, belonging to a private organization and for which the question of the implementation doesn’t exist, Eclipse Microprofile is a specification set maintained by a specialized working group placed under the auspices of the Eclipse Foundation, which has largely been adopted by many editors who provide different implementations, among which Quarkus, Wildfly, Open Liberty and Payara are from the most evangelical.
To resume, in this blog ticket we’ll going to implement the same web application using two different technologies, Spring Boot and Quarkus, such that to compare their respective two essential metrics: RSS (Resident Set Size) and TFR (Time to First Request). Please notice that the releases of the two Java stacks used here are the most recent as per this writing: Spring Boot 3.0.2 and Quarkus 2.16.2 implementing Eclipse Microprofile 4.2.
The Use Case
The use case that we’ve chosen for the web application to be implemented is a quite standard one: the one of a micro-service responsible to manage press releases. A press release is an official statement delivered to members of the news media for the purpose of providing information, creating an official statement, or making a public announcement. In our simplified case, a press release consists in a set of data like an unique name describing its subject, an author and a publisher.
The micro-service used to manage press releases is very straightforward. As any micro-service, it exposes a REST API allowing to CRUD press releases. All the required layers, like domain, model, entities, DTOs, mapping, persistence, service, are present as well. Our point here not being to discuss about the micro-services structure and modus operandi, but just to propose a common use case to be implemented in the two similar technologies, Spring Boot and Quarkus, such that to be able to compare their respective performances through the mentioned metrics.
Resident Set Size (RSS)
RSS is the amount of the RAM occupied by a process and consists of the sum of the following JVM spaces:
RSS is a very accurate metric and comparing applications based on it is a very reliable way to measure their associated performances and footprints.
Time to First Request (TFR)
There is a common concern to measure and compare applications startup times. However, logging it, which is how this is generally done, isn’t enough. The time that you’re seeing in your log file as being the application startup time, isn’t really accurate because it represents the time that your application or web server started, but not the one required such that your application starts to receive requests.
Application and web servers or servlet containers might start in a couple of milliseconds but this doesn’t mean that this is the time that your application is able to process requests. These platforms often are delaying work through the lazy initialization process and this may give a false indication about the TFR. Hence, in order to accurately determine the TFR, in this report we’re using Clément Escofier’s script time.js found here in the GitHub repository that illustrate the excellent book Reactive Systems in Java, by Clément Escoffier and Ken Finnigan, published by O'Reilly in December 2021 (https://www.oreilly.com/library/view/reactive-systems-in/9781492091714/).
The Spring Boot Implementation
In order to compare the metrics presented above for the two implementations, you need to clone and run the two projects. here are the steps required in order to experience the Spring Boot implementation:
$ git clone https://github.com/nicolasduminil/Comparing-Resident-Size
Set-Between-Spring-Boot-and-Quarkus.git metrics
$ cd metrics
$ git checkout spring-boot
$ mvn package
$ java -jar target/metrics.jar
Here you start by cloning the GIT repository and, once this operation finished, you go into the project's root directory and do a Maven build. Then you start the Spring Boot application by running the über JAR created by the spring-boot-maven-plugin. Now you can test the application via its exposed Swagger UI interface, by going to https://localhost:8081/q/swagger-ui . Please take a moment to use the Try it out feature that Swagger UI offers. The order of operations are as follows:
{
"pressReleaseId": 0,
"name": "AWS Lambda",
"author": "Nicolas DUMINIL",
"publisher": "ENI"
}
Please notice that, since the ID is automatically generated by a sequence, as explained, the first record will have the value of 1. You can use this value in GET /id and DELETE /id requests. Also notice that the press release name must be unique.
Now, once you have experienced for a while your micro-service, let’s see its associated RSS. Proceed as follows:
$ ps aux | grep metrics
nicolas?31598 3.5 1.8 13035944 598940 pts/1 Sl+?19:03?0:21 java -jar target/metrics.jar
nicolas?31771 0.0 0.0?9040?660 pts/2?S+?19:13?0:00 grep --color=auto metrics
$ ps -o pid,rss,command -p 31598
PID?RSS COMMAND
31598 639380 java -jar target/metrics.jar
Here we get the PID of our micro-service by looking up for its name and, once we got it, we can display its associated RSS. Notice that the command ps -o above will display the PID, the RSS and the starting command associated to the process which PID is passed as the -p argument. And as you may see, the RSS for our process is of 624 MB (639380 KB). If you’re hesitating of how to calculate this value, you can use the following command:
$ echo 639380/1024 | bc
624
As for the TFR, all you need to do is to run the time.js script, as follows:
$ node time.js "java -jar target/metrics.jar" "https://localhost:8080/rs
/"
173 ms
To resume, our Spring Boot micro-service has a RSS of 624 MB and a TFR of 173 ms.
The Quarkus Implementation
We need to perform these same operations such that to experience our Quarkus micro-service. Here are the required operations:
$ git checkout quarkus
$ mvn package quarkus:dev
Once that our Quarkus micro-service started, you may use again the Swager UI interface at https://localhost:8081/q/swagger-ui. And if you’re tired to use the graphical interface, then you may use the curl scripts provided in the repository (post.sh, get.sh, etc.) as shown below:
java -jar target/quarkus-ap/quarkus-run.jar &
./post.sh
./get.sh
./get-1.sh 1
./update.sh
./delete.sh
Now let’s see how do we are concerning our RSS and TFR.
$ ps aux | grep quarkus-run
nicolas?24776 20.2 0.6 13808088 205004 pts/3 Sl+ 16:27?0:04 java -jar target/quarkus-app/quarkus-run.jar
nicolas?24840 0.0 0.0?9040?728 pts/5?S+?16:28?0:00 grep--color=auto quarkus-run
$ ps -o pid,rss,command -p 24776
PID?RSS COMMAND
24776 175480 java -jar target/quarkus-app/quarkus-run.jar
$ echo 175480/1024 | bc
168
$ node time.js "java -jar target/metrics.jar" "https://localhost:8081/q
/swagger-ui"
121 ms
As you can see, our Quarkus micro-service uses an RSS of 168MB, i.e. almost 500MB less than the 624MB with Spring Boot ! Also, the TFR is slightly inferior (121ms vs 173ms).
Our exercise has compared the RSS and TFR metrics for the two micro-services executed with the HotSpot JVM (Oracle JDK 17). But with GraalVM, we can compile a micro-service into a native executable. Of course, we could compare the same RSS and TFR of native Spring Boot and Quarkus micro-services. But given that Spring Boot heavily relies on Java introspection, compiling to native code micro-services is more laborious and, consequently, the same comparative hasn't been conducted here.
Tecnólogo en Informática | DevOps | Backend Software Developer
1 年I'm happy to see that the Quarkus framework is receiving some attention! Also for Microprofile... i had one coworker who declared that Java EE (JakartaEE now) was dead a long time ago... i am happy to confirm that what i said and thought at the time was right: JavaEE is not dead, it is living a new life thanks to the Microprofile specification and also in Quarkus!