ColdFusion Memory Leaks: Part I – profiler introduction
Over the last year or so I’ve been dealing with memory leaks in ColdFusion. Some have been code related, but others seem to be issues with the way ColdFusion handles garbage collection of CFCs. Recently, we’ve made some breakthroughs at my company, so I thought I would share the steps that we took to identify memory leaks along with some interesting behaviors that we observed.
Hopefully, when I am finished, you will be on your way to changing your memory profile to look something like this… (This is an actual application profile under load)
In this post, I will show you the steps that I used to setup an environment that enabled me to identify the problem.
Step 1: configure your jvm: 5.0 is the way to go
The first thing that I tried was to use a profiling tool (i.e. jprobe or yourkit) against my existing coldfusion/jrun instance. This proved to be a mistake because the profiler added so much overhead to the jvm that the application became unresponsive. The solution was to use a Java 5 jvm. Jrun does not support Java 5 (JVM 1.5), but for the most part your application should run to the point that you can profile effectively.
Step 2: running with BEA Jrockit
For our example, I will suggest using the 1.5 jrockit jvm provided by BEA. The reason for this is because they have some powerful profiling tools that I will talk about later.
First, go to the following URL, and install the Jrockit 5.0 JDK
(For the rest of the example I will assume that you installed the JDK at C:\Program_Files\Java\jrockit-R26.4.0-jdk1.5.0_06\ )
you will also need to download a Jrockit Mission Control 1.0 license key. (you may need to register for that), save this file named as license.bea and move it to the following folder.
After that, modify your jvm.config file and change java.home to the following… (make sure to use forward slashes)
to enable profiling, you will need to add the following to your jvm args… (specify any port that you want)
Now restart the CF service and you are ready to go.
Step 3: memory leak detector
Now for the fun part… the Jrockit JDK ships with a tool called "Memory Leak Detector", To start using this, browse to the following folder…
Then double click on MemoryLeakDetector.jar (you may have to run it from the command line if that doesn’t work). The tool should start, and you should be able to specify the server and port (that you specified in jvm.config).
The next step is critical to effectively profile a ColdFusion application. From what I’ve observed, Internally, most of your variable data will be stored within objects of type coldfusion.runtime.variable. CFC classes don’t hold much data, so they take up a very small percentage of the jvm heap. We need to change the memory leak detector settings to look at small heap sizes. To do this, browse to File/Preferences/Trend and change "lowest heap usage to report" to 0.
Step 4: example
To show you how to use the memory leak detector, we will create an example, for this example I will create a cfc, this cfc has 2 methods, init() that returns itself, and doSomething() which will load 100 instances of itself into the variables scope of the object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<!--- file: test.cfc ---> <cfcomponent name="test"> <cfset variables.holderArray = arrayNew(1)> <cffunction name="init"> <cfreturn this> </cffunction> <cffunction name="doSomething"> <cfset var idx = ""> <cfloop from="1" to="100" index="idx"> <cfset arrayAppend(variables.holderArray) = createObject("component","test").init() /> </cfloop> </cffunction> </cfcomponent>
Next, create a simple cfm page that will load the cfc into memory and call the doSomething() function. Calling this .cfm page should create 101 instances of test in the application scope (1 loaded into application, and 100 loaded within itself)
1 2 3 4 5 6
<!--- file: test.cfm ---> <cfapplication name="test"> <cfset application.test = createObject("component","test")> <cfset application.test.doSomething()>
After you have executed the page, return to your memory leak detector and filter by "cf" (you can also filter by "cold" to see internal ColdFusion representations). You should now see something like this in the memory leak detector.
you will now see that we have created 101 instances of test.cfc in the memory heap (along with a reference to test.cfm that it is keeping alive, plus the empty classes it uses internally to identify the init() and doSomething() methods.
If you have made it to this point, you are on your way to profiling your application. If you leave the memory leak detector running under load, it will eventually track the growth of objects, and can be used to pinpoint potential problems. In my next post I will identify some of the potential problem behaviors of the ColdFusion engine, and how it can potentially "leak" object references in simple examples.
Credits and Reading materials
The basis of this strategy is outlined in greater detail in a pdf book created by Grant Straker. He focuses on other aspects of optimizing cf performance besides memory usage as well. If you are headed to Max, then I would highly recommend checking out his talk.
His pdf book is available at…
In my opinion this could be the most valuable $50 that you will ever spend on CF knowledge, and is well worth the money.
Mike Schierberl is a software engineer located in San Francisco, CA. He specializes in Cloud Computing, E-Commerce, and Continuous Integration.