An Insight Into Tuning Java-JVM via ColdFusion
Posted by Mike Brunt at 7:01 AM
I was sitting here this morning thinking of all the things I have seen relating to server performance over the past 11 years, since I first was brought on board by Allaire Corporation as a ColdFusion-Spectra consultant. This was prior to the Java based version of ColdFusion and I recall well the transition to Java that occurred when the version changed from ColdFusion 5 to ColdFusion MX 6 rapidly followed by ColdFusion MX 6.1 which included the first fully J2EE certified version of JRun, JRun4 if I recall that correctly. The main point here though was the transition to Java using JRun4 as the underlying container, that changed server tuning and troubleshooting dramatically and for the better after a learning curve.
With JRun and Java we have much more access to underlying and critical settings relating to thread and memory and I wanted to share what I look for in improving server performance or solving critical issues relating to performance and stability.
My first interest is always with the Java Virtual Machine (JVM) most clients I have helped have the Sun (Oracle) JVM which is the one shipped with ColdFusion. I start there because it literally is the "engine room" of everything. I use garbage collection logging to see exactly what is going on there by adding these arguments to the jvm.config file...
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -verbose:gc -Xloggc:cfwhispererGC.log
What I am looking for in the resulting log file is how many garbage collections are going on, how many full garbage collections (Full GC's) are going on and how long those Full GC's are taking. Here are two actual examples from my work showing what I have found to be a bad situation and also what I have found to be a good situation after tuning...
- First the bad results
- Garbage collections per minute = 39
- Full GC's per minute = .61
- Full GC duration 2.6 seconds
- Now the good results
- Garbage collections per minute = 4.3
- Full GC's per minute = .06
- Full GC duration 230 milliseconds
I also want to make sure that the permanent generation is not filling up, which it almost always is. Ideally we do not want the permanent generation to top 70% used.
Next I focus on the efficiency of threads. To observe this I used JRun metrics logging, I created a blog piece to show how this is enabled here. The efficient processing of threads is critical and we need to get to a point where the busy thread number is always low, where the number of handled threads per minute is high and where there are no delayed threads.
These are the things I look for and at in all of my work and I wanted to give an overall insight into to what I do in case it helps others.