2010-03-02 14 views
6

He escrito un script de carga de base de datos en ColdFusion y tengo un problema con el que el script se queda sin memoria lentamente. He dividido cada carga de tabla en su propio hilo con <cfthread> y llamo al recolector de basura cuando la memoria cae por debajo del 50% (asegurándose de tener 30 segundos entre llamadas gc() para evitar que el recolector de basura acapare la memoria) .Implicaciones de memoria para devolver una consulta desde un CFC

Creé un CFC para contener todas las consultas necesarias para el script. El script llama a la función CFC apropiada que luego devuelve la consulta, algunas de las cuales tienen más de 2 MB de tamaño. Cuando miro en el Monitor de Servidor en la vista de detalles de la página de Memoria para Hilos Activos, parece que mi CFC guarda una copia de la consulta en la memoria a pesar de que superé la variable de consulta y la variable salió del alcance al final de la función. Además, tengo una copia de la consulta en la memoria en mi hilo. Así que me quedan lo que parecen dos copias de la consulta en la memoria. ¿Esto es realmente lo que está pasando? Si es así, ¿cómo puedo eliminar una copia de la consulta de la memoria?

+0

¿alguna vez podría publicar su código gc() en alguna parte? Me encantaría ver tu enfoque. – Antony

+0

Mi código de recolección de basura está en http://www.fluentincode.com/2010/03/garbage-collection-in-coldfusion.html – stomcavage

Respuesta

11

Hay una gran cantidad de posibles problemas aquí, pero voy a tratar de destacar algunas de las cosas más importantes que debe considerar:

  1. por qué los hilos? ¿Necesitas los hilos? Hay un cierto punto en el que probablemente estás jugando demasiado por tu propio bien.
  2. Forzar manualmente la recolección de basura no es necesariamente una buena idea. Ajuste la JVM para realizar su recolección de basura automáticamente, pero tampoco exagere. La recolección de basura tiende a ser costosa y puede afectar el rendimiento de su aplicación si se ejecuta con demasiada frecuencia.
  3. ¿Cómo está instanciando su CFC? Si está instanciando el CFC en cada solicitud de la consulta, experimentará problemas de RAM con el tiempo, una pérdida de memoria lenta ya que los CFC se cargan en la memoria RAM demasiado rápido para que la recolección de basura se mantenga al día. Tu mejor opción es hacer de esto un singleton. (es decir, establecerlo en el alcance de la aplicación).
  4. Tenga en cuenta que var-scoping una variable no (por lo que yo lo entiendo) libera automáticamente la memoria tan pronto como la variable deja de ser utilizada. La memoria aún está reservada, aunque es probable que, de alguna manera, se haya marcado como parte de una generación efímera para que (¿probablemente?) Se limpie más rápido. Pero esto no garantiza nada.
  5. Si está buscando hilos activos, también es posible que la consulta no se borre hasta el final de la solicitud, no necesariamente al final de la llamada a la función. Parece impaciencia que lo motive a esperar que una consulta muera inmediatamente tan pronto como se complete la llamada a la función.
  6. ColdFusion queries are passed by reference, no por valor. Debería ser imposible obtener 2 copias de la consulta en la memoria, a menos que esté utilizando de alguna manera duplicate() o una función similar para copiar explícitamente la consulta.

Es probable que la consulta devuelva un puntero a la consulta desde su sentencia cfreturn. Esa consulta no se limpiará hasta que todos los procesos hayan terminado de hacer referencia a ella. Entonces, si pasa la consulta a algún otro proceso, no se limpiará la consulta de la memoria. Si establece esa consulta en una variable de sesión, por ejemplo, ese puntero no irá a ninguna parte hasta que la variable de sesión haya desaparecido, sin importar la frecuencia con la que trate de forzar la recolección de basura.

Sólo algunas cosas a considerar.

+1

Fantástica respuesta. No estaba esperando tratar de explicar todo eso, pero parece que no tengo que hacerlo. :-) –

+0

¡Oye, gracias! :) –

+0

Gracias. Es útil saber que las consultas se pasan por referencia. No pude encontrar esa información en mi búsqueda en línea. Estoy instanciando el CFC una vez por hilo. Estoy ejecutando varios subprocesos porque la memoria no parece estar completamente limpia, incluso con gc(), hasta que finalice una solicitud. Parece que un hilo es su propia solicitud, por lo que se multiplicó para la limpieza. He estado estableciendo la variable de consulta en una cadena vacía cuando terminé de usarla, y eso parece aliviar algunos de los problemas de memoria. – stomcavage

0

Tuve un problema similar con el procesamiento de una inserción de datos de gran tamaño, donde cada fila requiere un procesamiento extenso que implica varios CFC. Parece que las referencias JDBC ResultSet, Statement y Connection creadas por <cfquery> se mantienen hasta el final de la solicitud.Esto significa que anular la variable de consulta no afecta el uso de la memoria. La forma en que solucioné esto fue hacer una llamada de puerta de enlace a una función de CFC para procesar 100 filas, luego esa función realiza otra llamada de puerta de enlace para las siguientes 100 filas, etc. hasta que se procesen todas las filas. Como en realidad cada llamada de puerta de enlace individual sale, libera todos sus identificadores y se recupera la memoria.

+0

Muy interesante. Podría probar eso. Gracias. – stomcavage

Cuestiones relacionadas