Posts Tagged ‘JVM Heap’
In the previous post, I talked about the unusual phenomenon of seeing JVM shrink its heap and returning unused memory back to the operating system when running HFCD. But I didn’t talk much about how it happened. This post is to follow up on that…
First of all, the two key JVM parameters responsible for resizing JVM heap are:
- -XX:MinHeapFreeRatio (default is 40)
- -XX:MaxHeapFreeRatio (default is 70)
According to Sun (now Oracle),
By default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. This target range is set as a percentage by the parameters -XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>, and the total size is bounded below by -Xms and above by -Xmx .
It goes on to say:
With these parameters if the percent of free space in a generation falls below 40%, the size of the generation will be expanded so as to have 40% of the space free, assuming the size of the generation has not already reached its limit. Similarly, if the percent of free space exceeds 70%, the size of the generation will be shrunk so as to have only 70% of the space free as long as shrinking the generation does not decrease it below the minimum size of the generation.
Both Flash Builder and HFCD use the default -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio setting. As a matter of fact, by default, HFCD only sets -Xmx1024m and lets JVM tune itself.
Now take a look at the heap usage of Flash Builder when running the compiler internally. It looks obvious that the requirement for -XX:MaxHeapFreeRatio is not met. Therefore, no shrinking.
But take a look a the heap usage of HFCD. The used heap (blue line) drops so much (i.e. free space well exceeds 70% at the end) that JVM is able to resize the heap downward based on the default -XX:MaxHeapFreeRatio setting.
I also tried -server (HotSpot Server VM) and -client (HotSpot Client VM) on HFCD and manage to get the downward heap resizing to kick in.
However, there are two caveats you need to know:
- By default, JVM uses serial GC. If you start JVM by using the parallel GC (i.e. -XX:+UseParallelGC), you will NOT see this kind of huge downward resizing. I could be wrong but I think it’s because the parallel GC uses the adaptive size policy to control the size of the generations and ignore the -XX:MaxHeapFreeRatio setting.
- The charts above were generated by running Java 5/6 on Windows. The JVM on Mac OSX does adjust heap size downward from time to time but they are all very minor downward adjustments and it does not do that major downward resizing after finishing a full build.
There you go.
Every Flex developer and their mother knows that the Flex compiler uses a lot of memory to build applications! That’s not good… Fortunately, Adobe continues to work diligently to reduce the compiler’s memory usage. That being said, we still have to deal with what we currently have. We all know that once you get JVM to grow the heap to build your applications, it is tricky to make it give the memory back to the operating system. Take a look at the following example, I use Flash Builder to build the Flex framework projects that are setup in the Flex open source branch.
Flash Builder, at peak usage, uses just above 460 MB of memory to run a full build. After a forced garbage collection, the memory reading stays there… pretty much unchanged.
Of course, using the Windows Task Manager is hardly scientific. So I switch to Java Visual VM.
The orange line shows that the JVM heap does not shrink at all after a forced garbage collection. That kinda corroborates with the reading in the Windows Task Manager. There are many reasons why JVM does not shrink the heap. One obvious reason is that the used heap (blue line) stays relatively high there.
Now, I reconfigure Flash Builder to use HFCD to build the same Flex framework projects. The Windows Task Manager shows that the HFCD memory usage, at its peak, uses about 395MB of memory. But the memory usage of HFCD plunges to 80MB after running a full build. HFCD gives a huge chunk of memory back to the operating system!!
The Java Visual VM again, corroborates with the reading in the Windows Task Manager. Note that the orange line falls off a cliff after a full build. The JVM heap shrinks to a level well under 100MB!
If you are in the “memory-is-cheap” camp, you probably will not care. But it’s a big deal if you want to run some other applications during the day and when Flash Builder is holding onto a large chunk of system memory.
I will talk a bit more about this topic in the coming week.
BTW, I’ve updated HFCD 4 this morning. It includes several bug fixes and some minor performance enhancements. The good news is that HFCD 4 is still a lot faster than the FB built-in compiler in most medium-to-large FB workspaces.