2011-01-07 14 views
8

Googlers si tiene un volcado de pila con una raíz de coldfusion.runtime.CFDummyComponent siga leyendo.Memory Leak Looping cfmodule dentro de cffunction

actualización 2/22/2011

Marc Esher of MXUnit fame found the exact same bug in a different context. Su solución implica un gran bucle sobre una consulta resuelta al pasar de query="name" a from="1" to="#name.recordcount#" index="row". Otro enfoque que funciona es usar <cfthread> dentro del bucle como tal:

<cfloop ...> 
    <cfset threadName = "thread" & createUuid()> 
    <cfthread name="#threadName#"> 
     <!--- do stuff ---> 
    </cfthread> 
    <cfthread action="join" name="#threadName#"> 
</cfloop> 

Esto es muy eficaz cuando se ejecuta en situaciones en las que hay que hacer las cosas dentro del bucle como consultas y <cfmodule> dentro <cffunction> para que la memoria consumida es solo para esa iteración.

Viejo Pregunta

Con la esperanza de que alguien puede confirmar o dime lo que estoy haciendo mal. Puedo reproducir consistentemente un OOM en ejecución llamando al archivo oom.cfm (que se muestra a continuación). Al usar jconsole, puedo ver que la solicitud consume memoria y nunca la libera hasta que se completa. Parece que el problema es llamar al <cfmodule> dentro de <cffunction>, donde si hago un comentario sobre la llamada <cfmodule>, los elementos son basura recopilados mientras se ejecuta la solicitud.

ColdFusion versión: 9,0,1,274733

JVM Argumentos

java.home=C:/Program Files/Java/jdk1.6.0_18 
java.args=-server -Xms768m -Xmx768m -Dsun.io.useCanonCaches=false -XX:MaxPermSize=512m -XX:+UseParallelGC -Xbatch -Dcoldfusion.rootDir={application.home}/ -Djava.security.policy={application.home}/servers/41ep8/cfusion.ear/cfusion.war/WEB-INF/cfusion/lib/coldfusion.policy -Djava.security.auth.policy={application.home}/servers/41ep8/cfusion.ear/cfusion.war/WEB-INF/cfusion/lib/neo_jaas.policy -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=56033 

caso de prueba

oom.cfm (esto exige template.cfm a continuación - Adobe Bug #85736)

<cffunction name="fun" output="false" access="public" returntype="any" hint=""> 
    <cfset var local = structNew()/> 
    <!--- comment out cfmodule and no OOM ---> 
    <cfmodule template="template.cfm"> 
</cffunction> 

<cfset size = 1000 * 200> 
<cfloop from="1" to="#size#" index="idx"> 
    <cfset fun()> 
    <cfif NOT idx mod 1000> 
     <cflog file="se-err" text="#idx# of #size#"> 
    </cfif> 
</cfloop> 

template.cfm

<!--- I am empty! ---> 

Actualización # 2 (cfthread case from Elliott Sprehn - Adobe ColdFusion Bug #83359)

<cfthread name="test"> 
    <cfloop from="1" to="10000" index="i">  
    <cflog text="This is very bad.">  
    <cflock name="test" timeout="10">  
    </cflock> 
    </cfloop> 
    <!--- Sleep a very long time (10 minutes) ---> 
    <cfset sleep(600000)> 
</cfthread> 
+0

Me encontré con ocasiones en las que el multi-threading estaba matando mi memoria, y publiqué algunas aquí en SO. No me sorprendería si esto fuera similar. –

+1

¿Qué sucede si solo hace la llamada a cfmodule dentro del ciclo, omitiendo la función por completo? –

+0

@ Adam Tuttle: buen comentario, no había probado de esa manera. Cuando probé la recolección de basura se produce durante la solicitud, por lo que aún apunta a '' dentro de ''. – orangepips

Respuesta

5

yo no he encontrado esto antes, pero aquí es lo que creo que está pasando :

Cada vez que se invoca cfmodule, se crea un nuevo espacio de memoria para ello (que h, IIRC, es la principal diferencia entre it y cfinclude). Como está llamando al módulo cf en la función, el espacio de memoria cfmodule pertenece técnicamente al espacio de memoria de esa función. La memoria de la función está protegida de la recolección de elementos no utilizados hasta que la función finalice. Resultado: el montón se llena y se produce un error OOM.

No creo que llamar a esto una pérdida de memoria sea correcta, ya que se comporta correctamente, y cuando la función finalice, el recolector de basura puede borrar la retención de esa memoria. Sin embargo, puedo ver cómo podría ser un inconveniente.

+1

+1 porque esta es mi sospecha también. Sin embargo, es un error. Sin el módulo, llame a la asignación de memoria de la función * es * basura recolectada durante la solicitud. Por lo tanto, agregar una llamada a cfmodule dentro de ella debería hacerla parte de la memoria asignada de esa función y disponible para la recolección de elementos no utilizados a medida que la función sale del alcance (por ejemplo, el ciclo itera), pero esto claramente no ocurre. Pruebe seriamente el caso de prueba, con y sin el modue dentro de la función, y verá. – orangepips

+0

El espacio de memoria de cfmodule no está conectado a una variable con nombre, no sale del alcance hasta que finaliza la llamada a la función. Mal diseño o error? Personalmente, creo que es solo un mal diseño, pero podría estar equivocado. –

+0

Marcando esto como la respuesta, pero todavía estoy amargo en general (no en el contestador). – orangepips

3

Desafortunadamente, este problema se manifiesta con muchas etiquetas. Lo he visto con cflock dentro de cfthread.Escribe un bucle de ejecución muy largo en un cfthread que utiliza cflock, se te acabará la memoria al final. Lleva mucho tiempo, pero sucede. Apuesto a que el problema de retención también existe en solicitudes regulares, pero generalmente no se tiene un bucle que se ejecuta cientos de miles de veces con un cflock dentro para que nadie lo note.

me informó este error hace mucho tiempo, pero nunca fue resuelto: http://www.elliottsprehn.com/cfbugs/bugs/83359

La mejor solución por ahora es no utilizar cfmodule dentro de un bucle como este. Las etiquetas personalizadas realmente no estaban destinadas a llamadas 20k veces en una sola solicitud. En su lugar, querrá usar UDF. cfmodule es extremadamente caro de todos modos y usar un UDF será notablemente más rápido.

+0

Sphrehn: +1 He agregado su ejemplo a la pregunta original.Acordé que la noción de hacer la llamada tantas veces es mala, pero también es cuestión de trabajar con una base de código de 8 o 9 años, donde hay una gran cantidad de código escrito que espera ser llamado usando cfmodule/como una costumbre etiqueta. – orangepips

0

Aquí es una discusión de una versión ColdFusion 9 CFC problema de pérdida de memoria posiblemente relacionadas: http://forums.adobe.com/thread/1034324?start=0&tstart=0

ver este informe de error en él: https://bugbase.adobe.com/index.cfm?event=bug&id=3124148

No creo que Adobe lanzó una solución para versión alemana 9,01 pero supuestamente este problema se corrigió en la versión 10. Hay soluciones para la mayoría de las personas (dependiendo del alcance de su problema) para esto no muy diferente a lo que se ha descrito aquí.

+0

Esto debería ser un comentario a la pregunta OP porque no intenta responderla – Yaroslav