I'm presently trying to run down a memory (perceived) leak issue on an application that I've hosted for 3 years. In the past 3 months, this app has moved to the FarCry framework from a... less than stellar homebrew solution
At first, I thought it was Lucene shorting out, but I didn't have anything concrete beyond the amount of traffic hitting it. I installed FusionReactor, and although it's very helpful to watch the graphs, it still didn't give all that much accuracy into what was going on. Until...
A heap dump from yesterday revealed that railo.runtime.type.scope.ApplicationImpl had grown to 450 megs for just one site (the one converted recently). After asking around the Railo list, this object appears to be the application scope. Further suggestion was to loop over the keys, and use the built-in sizeOf and countOf functions to see what's going on (yay Railo!).
With some manual dumping of those keys, it appears that the cached HTML object types had grown far beyond expected. Way, far beyond. Ooops. So I cleared the cached objects, and poof, memory was manageable again.
So, on to a handy little file/CFC that will dump out scopes in Railo (I don't think these functions exist in Adobe CF, but I've not tested yet). Much thanks to Gert Franz, Michael Offner, Jay, and Peter Boughton (especially for those key loops Peter!)
First, you need this template. scopeDump.cfm
<!--- instantiate scope object --->
<cfset oGetScopeDetail=createObject("component", "scopeDump")>
<cfoutput>
<form action="" method="post">
<!--- set what scopes you want to dump --->
<select name="scope" id="scope">
<option value="application">Application</option>
<option value="session">Session</option>
<option value="cgi">CGI</option>
</select>
<input id="submit" name="submit" type="submit" value="GO!">
<cfif structkeyExists(form,"submit")>
<!--- You MUST get the struct to pass into the function --->
<cfset stScope=oGetScopeDetail.getDetail(structGet(form.scope))>
<cfif structkeyExists(stScope,'countOf')>
<p>Count of #form.scope#: #stScope.countOf#</p>
</cfif>
<cfif structkeyExists(stScope,'sizeOf')>
<p>Size of #form.scope#: #stScope.sizeOf#</p>
</cfif>
<!--- Looping over the returned objects in the structure --->
<cfif structkeyExists(stScope,'aItems')>
<table border="1">
<tr>
<td>Item</td>
<td>Count</td>
<td>Size</td>
</tr>
<cfloop from="1" to="#arraylen(stScope.aItems)#" index="i">
<tr>
<td>#stScope.aItems[i].name#</td>
<td>#stScope.aItems[i].countOf#</td>
<td>#stScope.aItems[i].sizeOf#</td>
</tr>
</cfloop>
</table>
</cfif>
</cfif>
</form>
</cfoutput>
You'll also need this little CFC, scopeDump.cfc
<cfcomponent displayname="scopeDump" >
<cffunction name="getDetail" access="remote" returntype="struct">
<cfargument name="scopeVar" required="yes" type="struct">
<cfset var rStruct=structnew()>
<cfset rStruct.countOf=numberformat(StructCount(arguments.scopeVar),',')>
<cfset rStruct.sizeOf=numberformat(SizeOf(arguments.scopeVar),',')>
<cfset var aItems=arraynew(1)>
<cfset var stItems=structnew()>
<cfset var tmp="">
<cfloop item="CurItem" collection=#arguments.scopeVar#>
<cfset stItems.name=CurItem>
<cfif isStruct(arguments.scopeVar[CurItem])>
<cfset stItems.countOf=numberformat(StructCount(arguments.scopeVar[CurItem]),',')>
<cfelse>
<cfset stItems.countOf=0>
</cfif>
<cfset stItems.sizeOf=numberformat(SizeOf(arguments.scopeVar[CurItem]),',')>
<cfset tmp=arrayappend(aItems,structcopy(stItems))>
<cfset tmp=structclear(stItems)>
</cfloop>
<cfset rStruct.aItems=aItems>
<cfreturn rStruct>
</cffunction>
</cfcomponent>