works que how forzar example español como collector java garbage-collection

how - garbage collector java que es



¿Cómo convencer a Java Garbage Collector para que se ejecute cuando el conjunto de trabajo es pequeño? (4)

Esta es otra pregunta "por favor, dígame cómo forzar al recolector de basura Java para que se ejecute". En nuestra aplicación, creo que tenemos buenas razones para hacer esto.

Esta es una aplicación de servidor, que normalmente tiene alrededor de 5M de objetos vivos. Una vez cada 5 minutos, realizamos una tarea de análisis que demora unos 60 segundos. Si se dispara un GC completo mientras se ejecuta el análisis, habrá alrededor de 40M de objetos vivos. Los objetos 35M adicionales se convierten en basura cuando se completa el análisis. El servidor debe seguir respondiendo a las solicitudes en todo momento (incluso mientras el análisis se está ejecutando).

Hemos encontrado que un GC completo toma alrededor de 1.5 segundos si se invoca cuando el análisis no se está ejecutando, pero alrededor de 15 segundos mientras el análisis se está ejecutando. Desafortunadamente, nuestro patrón de asignación es tal que los GC completos generalmente se activan durante el análisis, aunque el análisis solo se ejecuta el 20% del tiempo. (Cada tercera o cuarta ejecución de análisis dispara un GC completo.)

Agregué un código para llamar a System.gc (), que tanto desprecio, justo antes de comenzar una ejecución de análisis, si el espacio libre en la generación anterior está por debajo de un cierto umbral (5 GB). El beneficio fue muy importante: obtenemos tiempos de pausa de 1.5 segundos en lugar de tiempos de pausa de 15 segundos, y liberamos más basura en la negociación. Sin embargo, a veces la llamada a System.gc () se ignora, y terminamos con una pausa de 15 segundos unos minutos más tarde cuando el GC se dispara automáticamente.

Mi pregunta, entonces: ¿hay algo que podamos hacer para convencer más fuertemente al recolector de basura para que se ejecute? Estamos ejecutando 1.7.0_09-icedtea y usando el Parallel GC. Me gustaría (a) una forma confiable de forzar manualmente la recolección de basura, o (b) alguna forma de ajustar el colector para que tome una decisión automática más inteligente. (b) parece difícil, ya que no me queda claro cómo el coleccionista podría detectar que nuestro conjunto de trabajo varía de esta manera dramática.

Estoy dispuesto a recurrir a hackers sustanciales si es necesario; Este es un problema serio para nosotros. (Podríamos considerar los compactadores CMS o G1 como alternativas, pero desconfío del impacto en el rendimiento de CMS, y se dice que G1 se comporta mal frente a las matrices de bytes grandes que utilizamos).

addendum : En producción, nuestra experiencia hasta ahora ha sido que System.gc () generalmente desencadena una recolección de basura completa; Al menos, bajo las situaciones donde lo llamemos. (Solo lo llamamos una vez cada 10 a 30 minutos, con el montón algo pero no completamente lleno de basura). Sería bueno poder activar la recolección de basura de manera más confiable, pero nos está ayudando la mayor parte del tiempo.


Descubrí que java GC funciona muy mal con una gran cantidad de objetos (objetos de 20 a 100 m). su situación hubiera sido peor si esos objetos hubieran permanecido vivos, porque GC sería horrible, incluso si no hubiera nada que recolectar.

la solución es reducir el número de objetos (no la memoria total que está utilizando). Me atrevería a adivinar que la fase de análisis está usando colecciones y muchos envoltorios primitivos (entero, largo, etc.). Si este es el caso, una solución es cambiar a una biblioteca de colecciones primitivas. Una de esas bibliotecas es lo que creé para resolver un problema similar que encontré cuando ejecuté una simulación con objetos de 100 m en vivo durante mucho tiempo. Esa biblioteca se llama Banana , vea la wiki para más detalles.


En lugar de responder a su pregunta directamente (no puedo), me gustaría ofrecer una alternativa posible.

Parece que está asignando un gran número de matrices de bytes grandes durante su ejecución de análisis, y luego permite que se recojan de basura al final de la ejecución (o intente forzarlas a ser recolectadas justo antes de la siguiente ejecución).

En su lugar, si es posible, intente administrar su propio conjunto de matrices de bytes, de modo que, en el mejor de los casos, asigne todas las matrices necesarias una vez que se inicie la aplicación por primera vez, y luego vivan durante toda la vida de la aplicación, y No es necesario recoger la basura.

Esta idea puede, por supuesto, extenderse a estructuras de datos más complejas e instancias de objetos.

Todo esto es bastante más trabajo que simplemente asignar memoria cuando la necesita y "liberarla" cuando no lo hace, pero debería reducir considerablemente el trabajo que debe realizar el recolector de basura.


Su problema es que está ejecutando dos aplicaciones con requisitos y perfiles de memoria completamente diferentes en la misma JVM.

Ejecute el análisis de datos por separado, en un proceso que no esté dirigido al usuario, de modo que el servidor orientado al usuario siga respondiendo constantemente. Supongo que el análisis periódico genera un resumen o datos de resultados de algún tipo; haga que esté disponible para los usuarios finales enviándolo al servidor orientado hacia el usuario para que se pueda servir desde allí, o bien, deje que su front-end lo obtenga por separado del servidor de análisis.


Considere el uso de memoria no administrada, es decir, ByteBuffer en lugar de las matrices de bytes.

Solo puedo ofrecer un hack que necesitará un poco de ajuste y luego podría o no funcionar. Primero probaría las soluciones más sanas. Cuando quiera forzar el GC, hágalo asignando mucha memoria. Haga esto para que la memoria se pueda recuperar inmediatamente, pero para que no se pueda optimizar toda la asignación (algo así como sum += new byte[123456].hashCode() debería hacer). Tendrá que encontrar un método confiable para determinar cuándo detenerse. Un objeto con un finalizador podría decirle o tal vez ver runtime.getFreeMemory podría ayudar.