JVM microframeworks comparation
Hey, there we are!. Today we are going to talk about ‘Micronaut’ a JVM modular microframework. Micronaut is developed by Grails code team and they claim a minimal JAR size (around 8 Mb) and support Java, Groovy and Kotlin language. The syntax and annotation paradigm is very similar to Spring. Both, Spring and Micronaut, use reflexion in order to process java annotations, something that I don’t like because break completely the object-oriented paradigm and encapsulation. The main different of Micronaut is that they use reflexion at compile time, instead of runtime, this will give you a better start time.
On the other hand, they also implement their own dependency injection, based on annotation and an application context that handler all beans initialization and tracking (pretty much as Spring).
So well, let move on to a real example in order to see, about what we are talking about. We are going to setup this petstore example application and have a look how much memory they use at start time.
java -> petstore_pets_1 -> 162.5Mb
java -> petstore_mail_1 -> 58.52Mb
java -> petstore_offers_1 -> 149.6Mb
Mmm … It’s too far from this 8Mb that ‘OCI’, the Grails core team, claims. Why?. Maybe because they were talking about JAR size, however, this JAR will never work without a JVM. I am sure that if you use Java 11 and modules you will be able to reduce this JAR + JVM size. We already did the effort, and we got a microservice of 40 Mb using vertx framework.
In order to make a fair comparison between both framework, we are going to set up the “same” HelloWorld application.
We are going to run a performance test with 100 concurrent users that make one request per second, in order to see how each framework behaves in terms of memory consumption and threads.
around ... 76.3Mb
Threads details
The behavior’s as expected. Micronaut is an asynchronous none blocking threads framework (reactor), so we expected this behavior a fixed thread pool (even one thread would be enough) that handler all request. This is quite handy when you have to design and develop a middleware that acts as a proxy of several pieces each one with their own latency.
around ... 233.7Mb
… 1 min later the test was stopped…
Threads details
The behavior’s also as bad as expected. Spring has a huge legacy and has a lot of libraries that break the main golden rule of all ‘asynchronous none blocking’ frameworks:
Don’t Block the Event Loop
This is very important to keep in mind because if you use Micronaut you should pay attention to all of these third party libraries that you use in order to don’t finish up as Spring. Anyway, it’s quite interesting for this test, because this is a hello world application (there are not third-party libraries), and Spring behaves like an old synchronous and blocking framework.
Micronaut it’s a fresh air in the Spring world, they keep the annotation paradigm live at the same time that they remove all legacy ‘mess’. The result was a slim approach that handler in a smooth way all concurrency issues. I miss an eventbus as other JVM frameworks have, as Lagom, Akka, Vertx… that decouple the microservice (the business logic) with ‘how to deliver’ this logic.