22 votos

Java 6 Uso Excesivo De La Memoria

Hace Java 6 consumen más memoria que esperar para largish aplicaciones?

Tengo una aplicación que he estado desarrollando durante años, lo que ha sido, hasta ahora tomado unos 30-40 MB en mi particular configuración de la prueba; ahora con Java 6u10 y 11 es tomar varios cientos de mientras está activo. Rebota alrededor de un lote, en cualquier lugar entre 50 metros y 200 METROS, y cuando está inactivo, se hace la GC y la caída de la memoria de la derecha hacia abajo. Además, se genera millones de fallos de página. Todo esto es observado a través de Administrador de Tareas de Windows.

Así, me encontré bajo mi profiler (jProfiler) y el uso de jVisualVM, y dos de ellos indican la habitual moderada montón y perm-gen de los usos de unos 30 metros combinado, incluso cuando está completamente activo haciendo mi carga de la prueba de ciclo.

Así que estoy confundido! Y no sólo que requieran más memoria de la Memoria Virtual de Windows piscina - esto se está mostrando como 200M "Uso de memoria".

ACLARACIÓN: quiero ser muy claro en esto - observó más de un 18 horas con Java VisualVM la clase montón y perm gen montón han sido perfectamente estable. El asignado volátiles de la pila (el edén y el titular) se encuentra indiferentes a 16MB (que se alcanza en los primeros minutos), y el uso de esta memoria fluctúa en un perfecto patrón de crecimiento uniforme de 8MB 16MB, en la que el punto de GC patadas en una gotas de vuelta a 8MB. A través de este 18 horas, el sistema estaba bajo constante máxima de carga ya que yo estaba corriendo una prueba de esfuerzo. Este comportamiento es perfectamente y constantemente reproducible, visto a través de numerosas carreras. La única anomalía es que mientras esto ocurre en la memoria tomado de Windows, se observó a través del Administrador de Tareas, fluctúa todo el lugar desde 64 MB hasta 900 MB.

ACTUALIZACIÓN 2008-12-18: tengo ejecutar el programa con -Xms16M -Xmx16M sin aparente efecto adverso rendimiento está bien, el tiempo de ejecución total es aproximadamente el mismo. Pero el uso de la memoria en un corto plazo todavía alcanzó un máximo de 180 m de altura.

Actualización 2009-01-21: parece Que la respuesta puede ser el número de hilos - véase mi respuesta a continuación.


EDIT: Y me refiero a los millones de fallos de página literalmente - en la región de 30M+.

EDIT: tengo un 4G de la máquina, por lo que la 200M no es significativo en ese sentido.

13voto

Michael Borgwardt Puntos 181658

En respuesta a un debate en los comentarios a Ran respuesta, he aquí un caso de prueba que demuestra que la JVM va a liberar a su memoria el sistema operativo bajo ciertas circunstancias:

public class FreeTest
{
    public static void main(String[] args) throws Exception
    {
        byte[][] blob = new byte[60][1024*1024];
        for(int i=0; i<blob.length; i++)
        {
            Thread.sleep(500);
            System.out.println("freeing block "+i);
            blob[i] = null;
            System.gc();
        }
    }
}

Veo la JVM proceso de disminución de tamaño cuando el conteo llega a alrededor de 40, en tanto en Java 1.4 y Java 6 Jvm (del Sol).

Usted puede incluso ajustar el comportamiento exacto con el -XX:MaxHeapFreeRatio y -XX:MinHeapFreeRatio opciones -- algunas de las opciones de la página también pueden ayudar a responder la pregunta original.

9voto

Ran Biron Puntos 3015

Yo no sé acerca de los errores de página. pero se trata de la enorme memoria asignada para Java:

  1. La JVM de Sun sólo asigna memoria, nunca se desasigna (hasta JVM muerte) cancela la asignación de memoria sólo después de una relación específica entre la memoria interna y necesidades de memoria asignada cae por debajo de un (ajustables) valor. La JVM se inicia con la cantidad especificada en-Xms y puede ser extendido hasta por el monto especificado en -Xmx. No estoy seguro de cuál de las configuraciones por defecto. Cuando la JVM necesita más memoria (nuevos objetos / primitivas / matrices) se asigna un fragmento de todo desde el sistema operativo. Sin embargo, cuando la necesidad se desploma (momentánea de la necesidad, véase 2) no cancela la asignación de la memoria de la OS de inmediato, pero se mantiene a sí mismo hasta que la relación se ha alcanzado. Una vez me dijeron que JRockit se comporta mejor, pero no puedo comprobarlo.

  2. La JVM de Sun ejecuta un pleno de GC basa en varios factores desencadenantes. Uno de ellos es la cantidad de memoria disponible - cuando cae demasiado el JVM intenta realizar un completo GC para liberar a algunos más. Así que, cuando más que la memoria es asignada desde el sistema operativo (momentánea de la necesidad) la probabilidad de que un completo GC es baja. Esto significa que mientras que usted puede ver 30Mb de objetos "en vivo", no podría ser mucho más objetos "muertos" (no accesible), a la espera de una mesa a suceder. Sé yourkit tiene una gran vista llamados "muertos de los objetos", donde se pueden ver estas "sobras".

  3. En "servidor", el modo, la JVM de Sun corre GC en modo paralelo (a diferencia de la mayor serie de "parar el mundo" GC). Esto significa que si bien puede ser de basura para recoger, podría no ser recogido inmediatamente por otros hilos de tomar todo el tiempo de CPU disponible. Va a ser recogidos antes de llegar fuera de la memoria (bueno, un poco. ver http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html), si más de la memoria pueden ser asignados por el sistema operativo, puede ser antes de la GC se ejecuta.

Combinado, una gran inicial configuración de la memoria y las explosiones cortas de la creación de una gran cantidad de objetos de corta duración podría crear un escenario como el descrito.

edit: cambiado "nunca deallcoates" a "sólo después de la relación alcanzado".

7voto

Michael Borgwardt Puntos 181658

Exceso de hilo de la creación explica el problema a la perfección:

  • Cada Hilo tiene su propia pila, que es independiente de la memoria heap y por lo tanto no registrados por los perfiladores
  • El valor predeterminado de hilo tamaño de la pila es bastante grande, si mal no recuerdo 256KB (al menos lo fue para Java 1.3)
  • La banda de rodadura de la pila de memoria probablemente no se vuelven a utilizar, por lo que si usted crear y destruir un montón de hilos, usted obtendrá un montón de fallos de página

Si alguna vez realmente necesita tener cientos de hilos aound, el hilo tamaño de la pila puede ser configurado a través de la -Xss parámetro de línea de comandos.

4voto

Bill Michell Puntos 4879

La recolección de basura es un lugar arcanos de la ciencia. Como el estado de la técnica se desarrolla, onu-tuned comportamiento va a cambiar en respuesta.

Java 6 se ha predeterminado diferente GC comportamiento y diferentes "ergonomía" a las anteriores versiones de JVM. Si le dices que se puede usar más memoria (ya sea de forma explícita en la línea de comandos, o implícitamente, al no especificar nada más explícito), se utilizará más memoria, si cree que se puede mejorar el rendimiento.

En este caso, Java 6 parece creer que reservar el espacio extra que la pila puede crecer en la voluntad de dar un mejor rendimiento, probablemente porque cree que esto hará más objetos a morir en Edén, en el espacio, y limitar el número de objetos promovido al puesto de profesor titular de la generación de espacio. Y a partir de las especificaciones de su hardware, la JVM no creo que este extra reservados montón de espacio causará ningún problema. Tenga en cuenta que muchos (aunque no todos) de los supuestos de la JVM hace para llegar a las conclusiones están basadas en la "típica" de las aplicaciones, en lugar de su aplicación específica. También hace que las suposiciones basadas en el hardware y el sistema operativo de perfil.

Si la JVM ha hecho cosas equivocadas, puede influir en su comportamiento a través de la línea de comandos, aunque es fácil de hacer las cosas mal...

La información acerca de los cambios de rendimiento en java 6 se puede encontrar aquí.

Hay una discusión sobre la gestión de la memoria y el rendimiento de sus implicaciones en la Gestión de la Memoria de Papel Blanco.

3voto

Lawrence Dol Puntos 27976

Durante las últimas semanas me había causa para investigar y corregir un problema con un hilo objeto de agrupación (pre-Java 6 multi-hilo de ejecución de piscina), donde se iba a lanzar mucho más hilos de los necesarios. En los puestos de trabajo en cuestión no podría ser de hasta 200 temas innecesarios. Y los hilos estaban continuamente muriendo y los nuevos, en sustitución de ellos.

Haber corregido ese problema, pensé para ejecutar una prueba de nuevo, y ahora parece que el consumo de memoria es estable (a pesar de los 20 MB más que con mayores Jvm).

Así que mi conclusión es que los picos en la memoria se relaciona con el número de hilos de ejecución (varios cientos). Por desgracia no tengo tiempo para experimentar.

Si a alguien le gustaría experimentar y responder a esta con sus conclusiones, voy a aceptar que la respuesta; de lo contrario voy a aceptar este (después de los 2 días de periodo de espera).

También, la página de la tasa de errores es el camino hacia abajo (por un factor de 10).

También, las correcciones para el grupo de subprocesos corregido algunos problemas de contención.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X