cloudfoundry / java-buildpack-memory-calculator

Cloud Foundry JVM Memory Calculator
Apache License 2.0
645 stars 70 forks source link

Impossible to compute configuration for Boot application and 256M total memory #24

Closed sdeleuze closed 5 years ago

sdeleuze commented 5 years ago

A minimal Boot application is using 8000 classes. My typical non-trivial Spring Boot application (https://github.com/mixitconf/mixit) is loading around 10000 classes. Both run fine locally with -Xmx128M.

I would expect java-buildpack-memory-calculator to be able to compute a configuration with 256M of total memory, but it is currently not possible.

./java-buildpack-memory-calculator --loaded-class-count 8000 --thread-count 4 --total-memory 256m

allocated memory is greater than 256M available for allocation: -XX:MaxDirectMemorySize=10M, -XX:MaxMetaspaceSize=70312K, -XX:ReservedCodeCacheSize=240M, -Xss1M x 4 threads

The -XX:ReservedCodeCacheSize=240M looks suspicious to me.

nebhale commented 5 years ago

ReservedCodeCacheSize is the JVM's allocation for the JIT. In Java 8 and later (on Linux/x64) the default is 240M (up from 100M in 7 and earlier). My research suggests that this expansion was to support Java 8's Tiered Compilation. All anecdotal evidence points to the fact that attempting to adjust that value down (say back to the previous 100M) leads to enough JIT eviction that performance suffers by at least an order of magnitude.

This is just another example of the JVM defaulting to allocating a huge block of memory, outside of the heap, that isn't obviously visible. Your JVMs, regardless of where they are running (bare metal, VM, container) have always had this memory available to them. In a container, where memory utilization is constrained though, we have to make that allocation explicit and visible.