Spring Boot Versions: A Memory Usage Comparison

A Comparison of Memory Metrics Across Spring Boot Versions

With Spring Boot version 1.x reaching end-of-life in August, I thought it might be interesting to take a look at how memory usage changes over the different versions of Spring Boot.  For applications running on relatively small systems, it is useful to know how base memory usage might change after an upgrade.

I’ve used Java 8 and will cover Spring Boot versions 1.4.3, 1.5.21, 2.0.9, 2.1.5 and 2.1.6.  I used Visual VM to look at the memory use of the example application. The application is not run with any memory flags.

I kept the example fairly simple, but it includes the starters for JPA and web.  Additionally, it’s using SSL and accessing a MySQL database.  Examples often use in-memory databases, but I wasn’t sure how that would affect memory usage and also most people are going to be looking to upgrade production apps which rarely use in-memory databases.  I tried to strike a balance between creating something manageable as an example but having some elements of the real world in it.

A Brief Overview of Memory

This article isn’t meant to explain Java memory usage in detail, but it won’t hurt to go over the basics.  We’ll be looking at the heap and the metaspace for each version.

The heap is created by the JVM when our application is started and objects used by the application are stored there.

The metaspace replaced PermGen memory space starting with Java 8. It’s a native memory space where loaded classes and static information are stored.

Memory in an Empty Application

The first set of numbers I took was on an empty application.  As we can see, for an application that does absolutely nothing, the newer versions of Spring Boot have a slightly smaller heap but use more metaspace memory.

Table of memory numbers

Memory with an Entity Defined at Startup

My next step was to add a Book table to my MySQL database and wire up the application behind it.  We have a Book class with a few fields and the corresponding repository.  Next, I added a REST controller to operate on it.

@Entity
public class Book {
   @Id
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private Long id;
   private String isbn;
   private String title;
   private String author;

   // Constructors, getters, setters
}

I took two sets of numbers after adding the Book entity.  The first set is just after starting up the application.  We can see that the heap and metadata are a bit larger with our Book set up.  Aside from Metaspace Max; that one is all over the place.

with_entity_startup_numbers

Memory After Exercising the Entity

After taking the initial startup numbers, I ran a series of requests against the Book entity’s REST API using Postman.  Then I took the numbers again.  Versions 1.5.21 and 2.1.6 must have garbage collected since their amount of heap used decreased.  The used metaspace grew in all cases.

with_entity_post_run

For those of us, who like to visualize things, here are the heap graphs for each version from startup to after running the API calls.

Five small graphs plotting memory usage

Conclusion

Overall, the amount of memory used by Spring Boot is pretty consistent across the versions.  Obviously, real-world applications are going to be using more stuff and that will certainly have an effect, but it seems that upgrading Spring Boot alone isn’t going to lead to a problematic increase in memory used.

The example used is over on GitHub.  I need to point out a few things about the code.  There were things that needed to be changed between versions 1.x and 2.x, so you’ll find the code has areas commented out that are clearly marked as belonging to SpringBoot 1.x or 2.x.  Additionally, the Gradle Wrapper is for version 3.5, but Spring Boot 2.x doesn’t support it, so I had to change my project’s Gradle version back and forth as I was running the application against the different versions.  For version 1.4.3 and 1.5.21 you can use the wrapper.  For 2.0.9 and up, I just used the highest version my Eclipse had which was 5.5.