Comparativa Spring Boot vs Quarkus con JVM, GraalVM y Nativo

Antonio P. Ramos Rafael
5 min readApr 5, 2022

--

Dentro del ecosistema Java, Spring (en especial Spring Boot) es el framework defacto para desarrollar microservicios y es ampliamente usado en entornos empresariales, este viene sucumbiendo por tecnologías donde son más óptimas en tiempo de arranque y uso de memoria, por ejemplo NodeJS o Golang.

Es allí donde frameworks como Quarkus se presenta como disruptor dentro del ecosistema Java, a la fecha Quarkus tiene ya un nivel de madurez buena, donde por ejemplo hace un año teníamos extensiones para persistencia con Panache o programación reactiva en estado experimental, ahora son estables.

¡Comencemos el versus!

Tengamos en cuenta que esta comparativa será con Spring Boot 2.6, la versión 3 se viene con todo y veremos más adelante quién lleva la delantera. En ambos casos hemos implementado una aplicación reactiva que nos permite conectar a una Base de Datos en PostgreSQL y realizar un CRUD a una tabla mediante REST.

Equipo

  • MacBook Pro (16-inch, 2019)
  • Procesador: 2.6 GHz Intel Core i7 de seis núcleos
  • Memoria: 16 GB 2667 MHz DDR4
  • Gráficos: Intel UHD Graphics 630 1536 MB

Stack tecnológico

Quarkus:

  • Quarkus 2.7.1.Final
  • Resteasy Reactive Jackson
  • Hibernate Reactive Panache
  • Reactive Pg Client
  • Lombok

Spring Boot:

  • Spring Boot 2.6.4
  • Webflux
  • R2DBC
  • R2DBC PostgreSQL
  • Lombok
  • Spring Native (experimental)

Comparativa bajo JVM

La versión que tengo corriendo es Java 17, corresponde a la distribución de Amazon Correto.

En el proceso de Build, Quarkus fue más rápido (15.837s contra 27.963s de Spring Boot)

El tiempo de arranque es mejor con Quarkus, 1.621s contra 2.079s de Spring Boot:

(Izquierda Quarkus y derecha Spring Boot)

Al realizar una consulta (con HTTPie) el tiempo de ejecución es muy similar:

(Izquierda Quarkus y derecha Spring Boot)

Comparativa bajo GraalVM

Con la ayuda de SDKMAN tengo instalado GraalVM, igualmente con la versión Java 17:

En el proceso de build, Quarkus fue más rápido: 13.763s contra 25.939s de Spring Boot.

El tiempo de arranque sigue siendo mejor con Quarkus, 1.343s contra 2.018s de Spring Boot:

Comparativa en Nativo

Para esta última parte, de lado de Spring Boot vamos a trabajar con Spring Native que brinda soporte para generar un ejecutable nativo para nuestros proyectos. Puedes ver más información en el siguiente enlace: https://docs.spring.io/spring-native/docs/current/reference/htmlsingle

Además de tener instalado GraalVM, debemos instalar Native Image, esta tecnología nos permitirá la compilación anticipada (AOT) en contraparte de JIT que lo hace de forma selectiva de acuerdo a la frecuencia de la ejecución de los métodos de nuestras clases. Más información de cómo instalarlo aquí: https://www.graalvm.org/22.0/reference-manual/native-image

En el proceso de build del ejecutable nativo, Quarkus fue más rápido: 2m 1s contra 3m 2s de Spring Boot:

(En la parte superior Quarkus e inferior Spring Boot)

El tiempo de arranque es mejor con Quarkus: 0.025s contra 0.064s de Spring Boot:

Es interesante analizar el consumo de memoria con diferente carga a nuestra aplicación. Cuando arrancamos la aplicación y no realizamos ningún request, el consumo por parte de Quarkus es 15MB y en el caso de Spring Boot es 8MB. Vamos a realizar un par de pruebas con distintas cargas para observar el comportamiento de cada uno.

Con 5 request en un lapso de 10 segundos, Quarkus sólo usa 27MB y Spring Boot 59MB:

Al realizar una prueba de alta concurrencia (20 loops durante 60 segundos con múltiplos hilos) el escenario cambia. Spring Boot tiene un mejor rendimiento en uso de memoria, en promedio 175MB contra 310MB de Quarkus.

Además con Spring Boot se logra hacer más request en este rango de tiempo, 230,259 contra 162,633 con Quarkus:

Conclusiones

  • Quarkus tiene un menor tiempo de build con JVM, GraalVM y nativo.
  • Para ambos casos el tiempo de build es mayor al momento de generar en nativo, esto debido a que en el proceso se compila nuestro código, sus dependencias y genera todo el código de manera estática, además de incluir librerías de la JDK y el Substrate VM.
  • Quarkus tiene un mejor arranque. La diferencia es mayor cuando se ejecuta en nativo.
  • En carga intensiva y concurrente sobre la aplicación, Spring Boot tiene una amplia ventaja en el uso optimo de memoria (aprox. 45% menos que Quarkus), además de ser capaz de procesar aprox. 45% mas request en el mismo lapso de tiempo.

Es interesante ver y comprobar como ha ido evolucionando el ecosistema en JAVA, hace unos años era impensado tener estos tiempos de arranque y de respuesta en nuestras aplicaciones, además de un uso tan optimo en memoria.

Espero les haya sido de utilidad, en una próxima oportunidad vamos a llevar estas pruebas a contenedores y desplegarlas en AWS o GCP.

--

--