¿Cómo convencer a Java Garbage Collector para que se ejecute cuando el conjunto de trabajo es pequeño?
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é código para llamar a System.gc (), tan desdeñado, 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 se ignora la llamada a System.gc (), 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 firmemente al colector 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).
apéndice: En producción, nuestra experiencia hasta ahora ha sido que System.gc ()generalmente dispara una colecció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.