Java heap start (-Xms) in practice

The discussion on start (-Xms) and maximum (-Xmx) heap memory in Java is and old one. The consensus among admins is that both settings are best set to equal values in order to prevent internal Java reorganizations when heap changes are required. Before you follow this advice, you best understand that the starting heap is not fully claimed at the OS level and also that some garbage collection runs may not be triggered at all in your application.




Let us have a look at memory usage for an application running in production:


xms-and-xmx-in-action

What you see in this image is the free memory (the blue area) on an Ubuntu VPS for an application enduring respectable workload. On the left-hand side you can see the application running on similar start/max settings, both fixed at 5G. Even though the JVM initially claims the start heap memory, the OS does not. Also, garbage collection runs are rarely triggered, implying that the garbage heaps up. What you see here is that the JVM truly consumes all the heap memory it has been assigned as a start value, although in our case it takes almost two weeks before it actually does so.



On the right hand side, the max heap is the same. However, the start heap setting is only 2G. The actual OS memory usage is very quickly at a stable level, showing the well-known sawtooth without any "memory leaks". The garbage collector runs regularly. When the heap surpasses the start value and is later collected, the extra heap is returned to the pool.



We do not know how the comparison between extra garbage collection runs / heap reorganization versus a lot of garbage in memory plays out. It might well be that the latter is more effective than the former.



However, from the perspective of operational control, there is a lot of good to say for the settings where memory usage on the OS level is shown in a sawtooth pattern. Unusual behaviour, or just an increased workload, can be spotted much faster and correlated to the time of occurrence.



Either way, from the OS perspective, a much better way to view the heap start value is to see it as a target. When the memory usage is below the start setting, it allows usage to fill up to that value. When the memory usage is above the start setting, it will attempt to push it back down to the start level.