CFMX JVM Tuning - The difference between MaxPermSize and Heap Size
As a result of the CFMX/Commonspot upgrade I blogged a few days ago, I've been troubleshooting some CFMX crashing problems along with "java.lang.OutOfMemoryError" errors and have been tuning the JVM settings for the servers. Along the way I ended up doing a good bit of research on JVM settings and what the differences are between the Heap Size and the MaxPermSize.
It's fairly well documented on various blogs and discussion lists that both the JVM Heap Size and MaxPermSize are important when dealing with "out of memory" errors in CFMX, but I've never really completely understood what these setting or their values mean.
First off, what is the JVM Heap? The heap is memory that's been allocated to store Java classes and objects. The JVM heap is split up into several areas and newer/older objects are shuffled between the sections based on their age and use. The shuffling of object occurs during Garbage Collection, a process which also discards objects which are no longer used. Depending on system settings, garbage collection runs now and then, cleaning up objects and shuffling them around. More great information on Garbage collection in CFMX can be found on Brandon Purcell's blog and in Sun's tuning article on garbage collection (via Tom Link).
About heap size - it's generally a good idea to set the JVM's max heap size to at least 512, and no matter what the max is, the initial heap size should be set to the same value. Making these settings the same value prevents the JVM from frequently re-sizing the heap as it grows, something that can trigger frequent garbage collections and can degrade performance.
So when does it make sense to increase the JVM heap to a value larger than 512? Generally, no-one cares about this value till they start to get java.lang.OutOfMemoryError messages, and perhaps that's why you are reading this. If the JVM heap size is set too small, the server's memory slowly fills up and eventually an object is created and there's no more room in memory for it. This becomes the proverbial straw that breaks the camel's back and will cause your server to crash. Inversely, if you set the value too high, alot of junk objects build up in the heap and garbage collection can take a long time cleaning it up. This can cause a serious degradation in performance.
Again, I'll point at Brandon Purcell's blog for more help in finding the right size for the heap, though it also work to just adjust the heap size and watch the server for errors or performance problems.
That's a description of the heap, but what about this other setting set with -XX:MaxPermSize? Turns out this sets the size for something called the "Permanent Generation". A good definition for the Permanent Generation is found in the Sun article Frequently Asked Questions about Garbage Collection in the HotspotTM JavaTM Virtual Machine:
The permanent generation is used to hold reflective of the VM itself such as class objects and method objects. These reflective objects are allocated directly into the permanent generation, and it is sized independently from the other generations. Generally, sizing of this generation can be ignored because the default size is adequate. However, programs that load many classes may need a larger permanent generation.So the permanent generation contains information about the objects in the heap. Ah-ha! Now we can start to understand how these two numbers are related to each other. The heap stores the objects, and the permanent generation keeps track of information about the objects. Consequently, the more objects there are in the heap, the more information there is to be tracked about them, and the larger the permanent generation needs to be. Another quote from Sun's documentation comes in handy here:
For most applications the permanent generation is not relevant to garbage collector performance. However, some applications dynamically generate and load many classes. For instance, some implementations of JSP(TM) pages do this. If necessary, the maximum permanent generation size can be increased with MaxPermSize.This also applies to compiled ColdFusion class files. If there are alot of class files in /coldfusionmx/wwwroot/WEB-INF/cfclasses/, then you'll likely need to increase the MaxPermSize setting. Following this logic, if you have an application server with a large number of small class files, you are likely to need a larger MaxPermSize than if you have a server consisting of a small number of large class files. Note: Instructions on increasing the MaxPermSize are found in this ColdFusion MX: Tips for performance and scalability Technote. As it turns out in my recent Commonspot/CFMX upgrade, the new codebase must have generated more classes, or at least had more information generated by those class files. Even though the heap size was still large enough after the upgrade, I had to change the MaxPermSize from 128 to 256 to make the java.lang.OutOfMemoryError plaguing the site go away. Hopefully this explanation will come in handy for others tuning their memory settings! Added 4:14PM 5.28.04 Note: Important tidbit I forgot to add into this post initially - The MaxPermSize is in addition to the Heap, so if you add both of the numbers together you'll get the total size Jrun/CF should consume before blowing up.

# Posted By Charles Chapman | June 1, 2004 5:50 AM
Since CF templates are compiled to java classes, another way to say this is that "if there are alot of templates (and/or CFC methods) in the application(s) on the server, you'll likely need to increase the MaxPermSize setting."
# Posted By Tom Link | June 9, 2004 9:01 AM
http://www.markme.com/cantrell/archives/002181.cfm
Glad you got it worked out, and thanks for the valuable explanation.
# Posted By Christian Cantrell | June 9, 2004 2:46 PM
Drop +UseParallelGC. JVM 1.4.+ will use ParNewGC in a multiprocessor environment or the JVM will use the DefaultNew GC if the machine is uniprocessor (DefaultNew is more efficient than the parallel collectors, ParNew, on 1cpu machines).
Add these options to the JVM settings: -XX:MaxPermSize=128m -XX:PermSize=64m -XX:+UseConcMarkSweepGC -XX:NewSize=48m
Its actully pretty important on larger sites to make sure you set the PermSize in that you can get some really long 'stop the world' pauses while the JVM cleans up.
# Posted By Robi Sen | October 11, 2004 6:49 PM
# Posted By Cameron Childress | October 12, 2004 12:12 PM
# Posted By Robi Sen | October 12, 2004 1:24 PM
Also, as for max perm size, does anyone know how many templates (approx) need 128mb?
# Posted By Tom | March 17, 2005 7:54 AM
thanks in advance
# Posted By malleswar | August 3, 2005 8:02 AM
http://www.robisen.com/index.cfm?mode=entry&entry=FD4BE2FC-55DC-F2B1-FED0717CC1C7E0AF
http://www.robisen.com/index.cfm?mode=entry&entry=39E0B0C6-55DC-F2B1-FBBDB70CEC963D6D
http://www.robisen.com/index.cfm?mode=entry&entry=67789980-55DC-F2B1-FDEDE3B28F0E7A62
You really should read through the SUN JVM tuning faq. What are you trying to do? Solve a problem, tune your system for stability or performance, scale a application? Depending on your application and what you are doing you will want to have diffrent settings and its very much a unquie thing per system but the first link should give you a general idea. You should also profile your system first using some sort of automated load testing software as well as JVM monitoring tool like Jprofile or even JVMStat. Then you can get a base line of your system and see how its using memory. After that making changes makes sense. If you want to email me at robisen AT gmail DOT com I would be happy to send you a presentation on this topic as well as help you with your specific situation.
# Posted By robi | August 3, 2005 11:54 AM
# Posted By Patrick Hayden | July 4, 2007 3:41 AM
Not providing enough room for these classes is a common reason JVM's run out of mem under load.
Also a couple of quick comments to camerons post
1. you should use proper testing procedures to size your Xmx settings in that you can set your Xmx so large that garbage collection takes longer than it needs. A good rule is dont set your Xmx higher than 25% of what it uses under load but once again test and find the right setting for your app.
2. cameron says ' Making these settings the same value prevents the JVM from frequently re-sizing the heap as it grows, something that can trigger frequent garbage collections and can degrade performance.' actually this is not the reason since there is nothing wring with doing Xms 512 and Xmx 768. The reason to set them the same is heap fragmentation.
3. Another comment is.. hardly anyone tunes the young generation yet its usually the most used generation in a web app since thats where all initial web requests are created and destroyed. Usually the JVM will size this well for you but I often go ahead and test it with a minimum of about 20 to 25% of the total heap for a system i know will have heavy load. Often when i find my optimal settings I then make the young gen min and max the same once again for heap fragmentation reasons.
# Posted By robi | July 4, 2007 4:39 AM